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.
- package/README.md +2 -2
- package/build/Release/oracledb-6.6.0-darwin-arm64.node +0 -0
- package/build/Release/oracledb-6.6.0-darwin-arm64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-6.6.0-darwin-x64.node +0 -0
- package/build/Release/oracledb-6.6.0-darwin-x64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-6.6.0-js-buildinfo.txt +1 -0
- package/build/Release/oracledb-6.6.0-linux-arm64.node +0 -0
- package/build/Release/oracledb-6.6.0-linux-arm64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-6.6.0-linux-x64.node +0 -0
- package/build/Release/oracledb-6.6.0-linux-x64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-6.6.0-win32-x64.node +0 -0
- package/build/Release/oracledb-6.6.0-win32-x64.node-buildinfo.txt +1 -0
- package/examples/README.md +2 -0
- package/lib/configProviders/azure.js +167 -0
- package/lib/configProviders/base.js +99 -0
- package/lib/configProviders/ociobject.js +203 -0
- package/lib/connection.js +28 -12
- package/lib/constants.js +1 -0
- package/lib/errors.js +56 -1
- package/lib/impl/datahandlers/constants.js +3 -1
- package/lib/impl/datahandlers/vector.js +24 -9
- package/lib/impl/lob.js +27 -0
- package/lib/impl/resultset.js +26 -1
- package/lib/lob.js +52 -1
- package/lib/oracledb.js +54 -0
- package/lib/thin/connection.js +232 -16
- package/lib/thin/dbObject.js +4 -0
- package/lib/thin/lob.js +193 -1
- package/lib/thin/pool.js +15 -0
- package/lib/thin/protocol/capabilities.js +2 -0
- package/lib/thin/protocol/constants.js +29 -1
- package/lib/thin/protocol/messages/index.js +5 -1
- package/lib/thin/protocol/messages/lobOp.js +17 -5
- package/lib/thin/protocol/messages/transactionChangeState.js +99 -0
- package/lib/thin/protocol/messages/transactionSwitch.js +139 -0
- package/lib/thin/protocol/messages/withData.js +26 -6
- package/lib/thin/sqlnet/networkSession.js +2 -1
- package/lib/thin/sqlnet/paramParser.js +87 -50
- package/lib/thin/sqlnet/sessionAtts.js +13 -1
- package/lib/transformer.js +1 -2
- package/lib/types.js +1 -1
- package/lib/util.js +34 -2
- package/lib/version.js +2 -2
- package/package.json +1 -1
- package/build/Release/oracledb-6.5.1-darwin-x64.node +0 -0
- package/build/Release/oracledb-6.5.1-darwin-x64.node-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.5.1-js-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.5.1-linux-arm64.node +0 -0
- package/build/Release/oracledb-6.5.1-linux-arm64.node-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.5.1-linux-x64.node +0 -0
- package/build/Release/oracledb-6.5.1-linux-x64.node-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.5.1-win32-x64.node +0 -0
- package/build/Release/oracledb-6.5.1-win32-x64.node-buildinfo.txt +0 -1
package/lib/thin/connection.js
CHANGED
|
@@ -60,7 +60,13 @@ class ThinConnectionImpl extends ConnectionImpl {
|
|
|
60
60
|
async close() {
|
|
61
61
|
try {
|
|
62
62
|
if (this._protocol.txnInProgress) {
|
|
63
|
-
|
|
63
|
+
if (this.tpcContext) {
|
|
64
|
+
const message = this.createTpcRollbackMessage();
|
|
65
|
+
await this._protocol._processMessage(message);
|
|
66
|
+
} else {
|
|
67
|
+
await this.rollback();
|
|
68
|
+
}
|
|
69
|
+
this.tpcContext = null;
|
|
64
70
|
}
|
|
65
71
|
if (this._drcpEnabled) {
|
|
66
72
|
await this._sessRelease();
|
|
@@ -385,6 +391,9 @@ class ThinConnectionImpl extends ConnectionImpl {
|
|
|
385
391
|
info.elementType = this._parseTDSAttr(buf, info.elementTypeInfo);
|
|
386
392
|
if (info.elementType === types.DB_TYPE_OBJECT) {
|
|
387
393
|
await this._getElementTypeObj(info);
|
|
394
|
+
if (info.elementTypeClass.isXmlType) {
|
|
395
|
+
info.elementType = types.DB_TYPE_XMLTYPE;
|
|
396
|
+
}
|
|
388
397
|
}
|
|
389
398
|
} else {
|
|
390
399
|
if (info.attributes) { // skip for XML type as it has no attributes.
|
|
@@ -439,6 +448,27 @@ class ThinConnectionImpl extends ConnectionImpl {
|
|
|
439
448
|
end;
|
|
440
449
|
end if;
|
|
441
450
|
end;`;
|
|
451
|
+
|
|
452
|
+
// get column and datatype information in case of %ROWTYPE handling.
|
|
453
|
+
const getColumnsSQL = `
|
|
454
|
+
SELECT
|
|
455
|
+
column_name,
|
|
456
|
+
data_type,
|
|
457
|
+
data_type_owner,
|
|
458
|
+
case
|
|
459
|
+
when data_type in
|
|
460
|
+
('CHAR', 'NCHAR', 'VARCHAR2', 'NVARCHAR2', 'RAW')
|
|
461
|
+
then data_length
|
|
462
|
+
else 0
|
|
463
|
+
end,
|
|
464
|
+
nvl(data_precision, 0),
|
|
465
|
+
nvl(data_scale, 0)
|
|
466
|
+
from all_tab_cols
|
|
467
|
+
where owner = :owner
|
|
468
|
+
and table_name = :name
|
|
469
|
+
and hidden_column != 'YES'
|
|
470
|
+
order by column_id`;
|
|
471
|
+
|
|
442
472
|
const binds = [
|
|
443
473
|
{
|
|
444
474
|
name: "full_name",
|
|
@@ -517,32 +547,105 @@ class ThinConnectionImpl extends ConnectionImpl {
|
|
|
517
547
|
return info;
|
|
518
548
|
|
|
519
549
|
// process TDS and attributes cursor
|
|
520
|
-
info.
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
550
|
+
if (info.name.endsWith('%ROWTYPE')) {
|
|
551
|
+
const bindVal = [
|
|
552
|
+
{
|
|
553
|
+
name: "owner",
|
|
554
|
+
type: types.DB_TYPE_VARCHAR,
|
|
555
|
+
maxSize: 128,
|
|
556
|
+
dir: constants.BIND_IN,
|
|
557
|
+
values: [result.outBinds.schema],
|
|
558
|
+
},
|
|
559
|
+
{
|
|
560
|
+
name: "name",
|
|
561
|
+
type: types.DB_TYPE_VARCHAR,
|
|
562
|
+
maxSize: 128,
|
|
563
|
+
dir: constants.BIND_IN,
|
|
564
|
+
values: [info.name.substring(0, info.name.length - 8)]
|
|
565
|
+
}
|
|
566
|
+
];
|
|
567
|
+
const val = await this.execute(
|
|
568
|
+
getColumnsSQL, 1, bindVal, options, false
|
|
569
|
+
);
|
|
570
|
+
const attrRows = await val.resultSet._getAllRows();
|
|
524
571
|
info.attributes = [];
|
|
525
572
|
for (const row of attrRows) {
|
|
526
|
-
const
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
573
|
+
const metaData = {
|
|
574
|
+
name: row[0],
|
|
575
|
+
dataType: row[1],
|
|
576
|
+
dataTypeOwner: row[2],
|
|
577
|
+
maxSize: row[3],
|
|
578
|
+
dataPrecision: row[4],
|
|
579
|
+
dataScale: row[5],
|
|
580
|
+
};
|
|
581
|
+
if (!metaData.dataTypeOwner) {
|
|
582
|
+
const startPos = row[1].indexOf('(');
|
|
583
|
+
const endPos = row[1].indexOf(')');
|
|
584
|
+
if (endPos > startPos) {
|
|
585
|
+
metaData.dataType = metaData.dataType.substring(0, startPos) +
|
|
586
|
+
metaData.dataType.substring(
|
|
587
|
+
endPos + 1, metaData.dataType.length
|
|
588
|
+
);
|
|
532
589
|
}
|
|
533
|
-
} else {
|
|
534
|
-
attr.type = types.getTypeByColumnTypeName(row[3]);
|
|
535
590
|
}
|
|
536
|
-
info.attributes
|
|
591
|
+
this._addAttr(info.attributes, metaData);
|
|
537
592
|
}
|
|
538
|
-
}
|
|
593
|
+
} else {
|
|
594
|
+
info.version = result.outBinds.version;
|
|
595
|
+
const attrRows = await result.outBinds.attrs_rc._getAllRows();
|
|
596
|
+
if (attrRows.length > 0) {
|
|
597
|
+
// Its an object not a collection.
|
|
598
|
+
info.attributes = [];
|
|
599
|
+
for (const row of attrRows) {
|
|
600
|
+
const metaData = {
|
|
601
|
+
name: row[1],
|
|
602
|
+
dataType: row[3],
|
|
603
|
+
dataTypeOwner: row[4],
|
|
604
|
+
packageName: row[5],
|
|
605
|
+
oid: row[6]
|
|
606
|
+
};
|
|
607
|
+
this._addAttr(info.attributes, metaData);
|
|
608
|
+
}
|
|
539
609
|
|
|
540
|
-
|
|
610
|
+
}
|
|
611
|
+
await this._parseTDS(result.outBinds.tds, info);
|
|
612
|
+
}
|
|
541
613
|
info.partial = false;
|
|
542
614
|
return info;
|
|
543
615
|
|
|
544
616
|
}
|
|
545
617
|
|
|
618
|
+
//---------------------------------------------------------------------------
|
|
619
|
+
// _addAttr()
|
|
620
|
+
//
|
|
621
|
+
// Populates "attributes" object present in "attrList".
|
|
622
|
+
//---------------------------------------------------------------------------
|
|
623
|
+
_addAttr(attributes, attrInfo) {
|
|
624
|
+
const attr = { name: attrInfo.name };
|
|
625
|
+
if (attrInfo.dataTypeOwner) {
|
|
626
|
+
attr.type = types.DB_TYPE_OBJECT;
|
|
627
|
+
attr.typeClass = this._getDbObjectType(
|
|
628
|
+
attrInfo.dataTypeOwner,
|
|
629
|
+
attrInfo.dataType,
|
|
630
|
+
attrInfo.packageName,
|
|
631
|
+
attrInfo.oid
|
|
632
|
+
);
|
|
633
|
+
|
|
634
|
+
if (attr.typeClass.isXmlType) {
|
|
635
|
+
attr.type = types.DB_TYPE_XMLTYPE;
|
|
636
|
+
}
|
|
637
|
+
if (attr.typeClass.partial) {
|
|
638
|
+
this._partialDbObjectTypes.push(attr.typeClass);
|
|
639
|
+
}
|
|
640
|
+
} else {
|
|
641
|
+
attr.type = types.getTypeByColumnTypeName(attrInfo.dataType);
|
|
642
|
+
attr.maxSize = attrInfo.maxSize;
|
|
643
|
+
attr.precision = attrInfo.dataPrecision;
|
|
644
|
+
attr.scale = attrInfo.dataScale;
|
|
645
|
+
}
|
|
646
|
+
attributes.push(attr);
|
|
647
|
+
}
|
|
648
|
+
|
|
546
649
|
//---------------------------------------------------------------------------
|
|
547
650
|
// _populatePartialDbObjectTypes()
|
|
548
651
|
//
|
|
@@ -633,6 +736,7 @@ class ThinConnectionImpl extends ConnectionImpl {
|
|
|
633
736
|
this.serviceName = '';
|
|
634
737
|
this.remoteAddress = '';
|
|
635
738
|
this.comboKey = null; // used in changePassword API
|
|
739
|
+
this.tpcContext = null;
|
|
636
740
|
|
|
637
741
|
this.nscon = new nsi();
|
|
638
742
|
finalizationRegistry.register(this, this.nscon);
|
|
@@ -948,6 +1052,14 @@ class ThinConnectionImpl extends ConnectionImpl {
|
|
|
948
1052
|
this._dbOp = dbOp;
|
|
949
1053
|
}
|
|
950
1054
|
|
|
1055
|
+
setExternalName(value) {
|
|
1056
|
+
this.externalName = value;
|
|
1057
|
+
}
|
|
1058
|
+
|
|
1059
|
+
setInternalName(value) {
|
|
1060
|
+
this.internalName = value;
|
|
1061
|
+
}
|
|
1062
|
+
|
|
951
1063
|
setClientInfo(clientInfo) {
|
|
952
1064
|
this._clientInfoModified = true;
|
|
953
1065
|
this._clientInfo = clientInfo;
|
|
@@ -986,6 +1098,102 @@ class ThinConnectionImpl extends ConnectionImpl {
|
|
|
986
1098
|
return lobImpl;
|
|
987
1099
|
}
|
|
988
1100
|
|
|
1101
|
+
// Check the state returned by the tpcCommit() call.
|
|
1102
|
+
checkTpcCommitState(state, onePhase) {
|
|
1103
|
+
if ((onePhase && state !== constants.TNS_TPC_TXN_STATE_READ_ONLY
|
|
1104
|
+
&& state !== constants.TNS_TPC_TXN_STATE_COMMITTED) ||
|
|
1105
|
+
(!onePhase && state !== constants.TNS_TPC_TXN_STATE_FORGOTTEN)) {
|
|
1106
|
+
errors.throwErr(errors.ERR_UNKNOWN_TRANSACTION_STATE, state);
|
|
1107
|
+
}
|
|
1108
|
+
}
|
|
1109
|
+
|
|
1110
|
+
// Creates a two-phase commit message suitable for committing a transaction.
|
|
1111
|
+
createTpcCommitMessage(xid, onePhase) {
|
|
1112
|
+
const message = new messages.TransactionChangeStateMessage(this);
|
|
1113
|
+
message.operation = constants.TNS_TPC_TXN_COMMIT;
|
|
1114
|
+
message.state = (onePhase == 0) ? constants.TNS_TPC_TXN_STATE_COMMITTED :
|
|
1115
|
+
constants.TNS_TPC_TXN_STATE_READ_ONLY;
|
|
1116
|
+
message.xid = xid;
|
|
1117
|
+
message.context = this.tpcContext;
|
|
1118
|
+
return message;
|
|
1119
|
+
}
|
|
1120
|
+
|
|
1121
|
+
// Creates a two-phase commit rollback message suitable for use in both
|
|
1122
|
+
// the close() method and explicitly by the user.
|
|
1123
|
+
createTpcRollbackMessage(xid = null) {
|
|
1124
|
+
const message = new messages.TransactionChangeStateMessage(this);
|
|
1125
|
+
message.operation = constants.TNS_TPC_TXN_ABORT;
|
|
1126
|
+
message.state = constants.TNS_TPC_TXN_STATE_ABORTED;
|
|
1127
|
+
message.xid = xid;
|
|
1128
|
+
message.context = this.tpcContext;
|
|
1129
|
+
return message;
|
|
1130
|
+
}
|
|
1131
|
+
|
|
1132
|
+
//---------------------------------------------------------------------------
|
|
1133
|
+
// tpcBegin()
|
|
1134
|
+
//---------------------------------------------------------------------------
|
|
1135
|
+
async tpcBegin(xid, flags, timeout) {
|
|
1136
|
+
const message = new messages.TransactionSwitchMessage(this);
|
|
1137
|
+
message.operation = constants.TNS_TPC_TXN_START;
|
|
1138
|
+
message.xid = xid;
|
|
1139
|
+
message.flags = flags;
|
|
1140
|
+
message.timeout = timeout;
|
|
1141
|
+
await this._protocol._processMessage(message);
|
|
1142
|
+
this.tpcContext = message.context;
|
|
1143
|
+
}
|
|
1144
|
+
|
|
1145
|
+
//---------------------------------------------------------------------------
|
|
1146
|
+
// tpcCommit()
|
|
1147
|
+
//---------------------------------------------------------------------------
|
|
1148
|
+
async tpcCommit(xid, onePhase) {
|
|
1149
|
+
const message = this.createTpcCommitMessage(xid, onePhase);
|
|
1150
|
+
await this._protocol._processMessage(message);
|
|
1151
|
+
this.checkTpcCommitState(message.state, onePhase);
|
|
1152
|
+
}
|
|
1153
|
+
|
|
1154
|
+
//---------------------------------------------------------------------------
|
|
1155
|
+
// tpcEnd()
|
|
1156
|
+
//---------------------------------------------------------------------------
|
|
1157
|
+
async tpcEnd(xid, flags) {
|
|
1158
|
+
const message = new messages.TransactionSwitchMessage(this);
|
|
1159
|
+
message.operation = constants.TNS_TPC_TXN_DETACH;
|
|
1160
|
+
message.xid = xid;
|
|
1161
|
+
message.context = this.tpcContext;
|
|
1162
|
+
message.flags = flags;
|
|
1163
|
+
await this._protocol._processMessage(message);
|
|
1164
|
+
this.tpcContext = null;
|
|
1165
|
+
}
|
|
1166
|
+
|
|
1167
|
+
//---------------------------------------------------------------------------
|
|
1168
|
+
// tpcPrepare()
|
|
1169
|
+
//---------------------------------------------------------------------------
|
|
1170
|
+
async tpcPrepare(xid) {
|
|
1171
|
+
const message = new messages.TransactionChangeStateMessage(this);
|
|
1172
|
+
message.operation = constants.TNS_TPC_TXN_PREPARE;
|
|
1173
|
+
message.xid = xid;
|
|
1174
|
+
message.context = this.tpcContext;
|
|
1175
|
+
await this._protocol._processMessage(message);
|
|
1176
|
+
if (message.state === constants.TNS_TPC_TXN_STATE_REQUIRES_COMMIT) {
|
|
1177
|
+
return true;
|
|
1178
|
+
} else if (message.state === constants.TNS_TPC_TXN_STATE_READ_ONLY) {
|
|
1179
|
+
return false;
|
|
1180
|
+
}
|
|
1181
|
+
|
|
1182
|
+
errors.throwErr(errors.ERR_UNKNOWN_TRANSACTION_STATE, message.state);
|
|
1183
|
+
}
|
|
1184
|
+
|
|
1185
|
+
//---------------------------------------------------------------------------
|
|
1186
|
+
// tpcRollback()
|
|
1187
|
+
//---------------------------------------------------------------------------
|
|
1188
|
+
async tpcRollback(xid) {
|
|
1189
|
+
const message = this.createTpcRollbackMessage(xid);
|
|
1190
|
+
await this._protocol._processMessage(message);
|
|
1191
|
+
if (message.state !== constants.TNS_TPC_TXN_STATE_ABORTED) {
|
|
1192
|
+
errors.throwErr(errors.ERR_UNKNOWN_TRANSACTION_STATE, message.state);
|
|
1193
|
+
}
|
|
1194
|
+
}
|
|
1195
|
+
|
|
1196
|
+
|
|
989
1197
|
//---------------------------------------------------------------------------
|
|
990
1198
|
// Returns the statement cache size for the statement cache maintained by
|
|
991
1199
|
// the connection object
|
|
@@ -1009,6 +1217,10 @@ class ThinConnectionImpl extends ConnectionImpl {
|
|
|
1009
1217
|
return '';
|
|
1010
1218
|
}
|
|
1011
1219
|
|
|
1220
|
+
getExternalName() {
|
|
1221
|
+
return this.externalName;
|
|
1222
|
+
}
|
|
1223
|
+
|
|
1012
1224
|
//---------------------------------------------------------------------------
|
|
1013
1225
|
// Returns the Oracle Database instance name associated with the connection.
|
|
1014
1226
|
//---------------------------------------------------------------------------
|
|
@@ -1016,6 +1228,10 @@ class ThinConnectionImpl extends ConnectionImpl {
|
|
|
1016
1228
|
return this.instanceName;
|
|
1017
1229
|
}
|
|
1018
1230
|
|
|
1231
|
+
getInternalName() {
|
|
1232
|
+
return this.internalName;
|
|
1233
|
+
}
|
|
1234
|
+
|
|
1019
1235
|
//---------------------------------------------------------------------------
|
|
1020
1236
|
// Returns the Oracle Database domain name associated with the connection.
|
|
1021
1237
|
//---------------------------------------------------------------------------
|
package/lib/thin/dbObject.js
CHANGED
|
@@ -397,10 +397,14 @@ class ThinDbObjectImpl extends DbObjectImpl {
|
|
|
397
397
|
case types.DB_TYPE_BOOLEAN:
|
|
398
398
|
return buf.readBool();
|
|
399
399
|
case types.DB_TYPE_OBJECT:
|
|
400
|
+
case types.DB_TYPE_XMLTYPE:
|
|
400
401
|
isNull = buf.getIsAtomicNull();
|
|
401
402
|
if (isNull)
|
|
402
403
|
return null;
|
|
403
404
|
obj = new ThinDbObjectImpl(typeClass);
|
|
405
|
+
if (obj._objType.isXmlType) {
|
|
406
|
+
return readXML(obj._objType._connection, buf.readBytesWithLength());
|
|
407
|
+
}
|
|
404
408
|
if (obj._objType.isCollection || this._objType.isCollection) {
|
|
405
409
|
obj.packedData = Buffer.from(buf.readBytesWithLength());
|
|
406
410
|
} else {
|
package/lib/thin/lob.js
CHANGED
|
@@ -31,6 +31,7 @@ const LobImpl = require('../impl/lob.js');
|
|
|
31
31
|
const constants = require('./protocol/constants.js');
|
|
32
32
|
const LobOpMessage = require('./protocol/messages/lobOp.js');
|
|
33
33
|
const errors = require('../errors.js');
|
|
34
|
+
const types = require('../types.js');
|
|
34
35
|
|
|
35
36
|
class ThinLobImpl extends LobImpl {
|
|
36
37
|
|
|
@@ -54,15 +55,31 @@ class ThinLobImpl extends LobImpl {
|
|
|
54
55
|
await this.conn._protocol._processMessage(message);
|
|
55
56
|
if (options.operation === constants.TNS_LOB_OP_READ) {
|
|
56
57
|
return (message.data) ? message.data : null;
|
|
58
|
+
} else if (
|
|
59
|
+
options.operation === constants.TNS_LOB_OP_FILE_EXISTS ||
|
|
60
|
+
options.operation === constants.TNS_LOB_OP_FILE_ISOPEN
|
|
61
|
+
) {
|
|
62
|
+
return message.boolFlag;
|
|
57
63
|
} else {
|
|
58
64
|
return message.amount;
|
|
59
65
|
}
|
|
60
66
|
}
|
|
61
67
|
|
|
68
|
+
//---------------------------------------------------------------------------
|
|
69
|
+
// getChunkSize()
|
|
70
|
+
//
|
|
71
|
+
// Internal method for returning the chunk size of the LOB.
|
|
72
|
+
//---------------------------------------------------------------------------
|
|
62
73
|
getChunkSize() {
|
|
63
74
|
return this._chunkSize;
|
|
64
75
|
}
|
|
65
76
|
|
|
77
|
+
//---------------------------------------------------------------------------
|
|
78
|
+
// _getChunkSizeAsync()
|
|
79
|
+
//
|
|
80
|
+
// Internal method for returning the chunk size of the LOB fetched from
|
|
81
|
+
// the database.
|
|
82
|
+
//---------------------------------------------------------------------------
|
|
66
83
|
async _getChunkSizeAsync() {
|
|
67
84
|
this.checkConn();
|
|
68
85
|
const options = {
|
|
@@ -73,29 +90,76 @@ class ThinLobImpl extends LobImpl {
|
|
|
73
90
|
this._chunkSize = this._pieceSize = await this._sendMessage(options);
|
|
74
91
|
}
|
|
75
92
|
|
|
93
|
+
//---------------------------------------------------------------------------
|
|
94
|
+
// getLength()
|
|
95
|
+
//
|
|
96
|
+
// Internal method for returning the length of a LOB.
|
|
97
|
+
//---------------------------------------------------------------------------
|
|
76
98
|
getLength() {
|
|
77
99
|
return this._length;
|
|
78
100
|
}
|
|
79
101
|
|
|
102
|
+
//---------------------------------------------------------------------------
|
|
103
|
+
// getPieceSize()
|
|
104
|
+
//
|
|
105
|
+
// Internal method returning the size to use for each piece that is
|
|
106
|
+
// transferred when reading from the LOB.
|
|
107
|
+
//---------------------------------------------------------------------------
|
|
80
108
|
getPieceSize() {
|
|
81
109
|
return this._pieceSize;
|
|
82
110
|
}
|
|
83
111
|
|
|
112
|
+
//---------------------------------------------------------------------------
|
|
113
|
+
// setPieceSize()
|
|
114
|
+
//
|
|
115
|
+
// Internal method to set the pieceSize for LOBs.
|
|
116
|
+
//---------------------------------------------------------------------------
|
|
84
117
|
setPieceSize(value) {
|
|
85
118
|
this._pieceSize = value;
|
|
86
119
|
}
|
|
87
120
|
|
|
121
|
+
//---------------------------------------------------------------------------
|
|
122
|
+
// getType()
|
|
123
|
+
//
|
|
124
|
+
// Internal method returning the datatype of LOBs.
|
|
125
|
+
//---------------------------------------------------------------------------
|
|
88
126
|
getType() {
|
|
89
127
|
return this.dbType;
|
|
90
128
|
}
|
|
91
129
|
|
|
130
|
+
//---------------------------------------------------------------------------
|
|
131
|
+
// getData()
|
|
132
|
+
//
|
|
133
|
+
// Internal method returning the data obtained from the database.
|
|
134
|
+
//---------------------------------------------------------------------------
|
|
92
135
|
async getData(offset = 1, len = this._length) {
|
|
136
|
+
let shouldClose = false;
|
|
93
137
|
if (!len) {
|
|
94
138
|
len = this._length;
|
|
95
139
|
}
|
|
96
|
-
|
|
140
|
+
if (this.dbType === types.DB_TYPE_BFILE) {
|
|
141
|
+
if (!await this.isFileOpen()) {
|
|
142
|
+
shouldClose = true;
|
|
143
|
+
await this.openFile();
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
let data;
|
|
147
|
+
// if read fails and BFILE was opened by application, we close it.
|
|
148
|
+
try {
|
|
149
|
+
data = await this.read(offset, len);
|
|
150
|
+
} finally {
|
|
151
|
+
if (shouldClose) {
|
|
152
|
+
await this.closeFile();
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return data;
|
|
97
156
|
}
|
|
98
157
|
|
|
158
|
+
//---------------------------------------------------------------------------
|
|
159
|
+
// read()
|
|
160
|
+
//
|
|
161
|
+
// Internal method for reading a portion (or all) of the data in the LOB.
|
|
162
|
+
//---------------------------------------------------------------------------
|
|
99
163
|
async read(offset, length) {
|
|
100
164
|
this.checkConn();
|
|
101
165
|
const options = {
|
|
@@ -108,6 +172,11 @@ class ThinLobImpl extends LobImpl {
|
|
|
108
172
|
return await this._sendMessage(options);
|
|
109
173
|
}
|
|
110
174
|
|
|
175
|
+
//---------------------------------------------------------------------------
|
|
176
|
+
// write()
|
|
177
|
+
//
|
|
178
|
+
// Internal method for writing data to the LOB object.
|
|
179
|
+
//---------------------------------------------------------------------------
|
|
111
180
|
async write(offset, data) {
|
|
112
181
|
this.checkConn();
|
|
113
182
|
const options = {
|
|
@@ -120,6 +189,11 @@ class ThinLobImpl extends LobImpl {
|
|
|
120
189
|
this._length += data.length;
|
|
121
190
|
}
|
|
122
191
|
|
|
192
|
+
//---------------------------------------------------------------------------
|
|
193
|
+
// getCsfrm()
|
|
194
|
+
//
|
|
195
|
+
// Return the character set encoding used by the LOB.
|
|
196
|
+
//---------------------------------------------------------------------------
|
|
123
197
|
getCsfrm() {
|
|
124
198
|
if (this.dbType._csfrm !== constants.CSFRM_NCHAR) {
|
|
125
199
|
if (this._locator[constants.TNS_LOB_LOC_OFFSET_FLAG_3] &
|
|
@@ -155,11 +229,60 @@ class ThinLobImpl extends LobImpl {
|
|
|
155
229
|
await this._getChunkSizeAsync();
|
|
156
230
|
}
|
|
157
231
|
|
|
232
|
+
//---------------------------------------------------------------------------
|
|
233
|
+
// fileExists()
|
|
234
|
+
//
|
|
235
|
+
// Internal method for returning whether the file referenced by a BFILE
|
|
236
|
+
// exists.
|
|
237
|
+
//---------------------------------------------------------------------------
|
|
238
|
+
async fileExists() {
|
|
239
|
+
this.checkConn();
|
|
240
|
+
const options = {
|
|
241
|
+
operation: constants.TNS_LOB_OP_FILE_EXISTS,
|
|
242
|
+
sourceLobImpl: this,
|
|
243
|
+
};
|
|
244
|
+
return await this._sendMessage(options);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
//---------------------------------------------------------------------------
|
|
248
|
+
// getDirFileName()
|
|
249
|
+
//
|
|
250
|
+
// Internal method for returning the directory alias and name of the file
|
|
251
|
+
// referenced by a BFILE
|
|
252
|
+
//---------------------------------------------------------------------------
|
|
253
|
+
getDirFileName() {
|
|
254
|
+
const dirNameOffset = constants.TNS_LOB_LOC_FIXED_OFFSET + 2;
|
|
255
|
+
const dirNameLen = this._locator.readUInt16BE(
|
|
256
|
+
constants.TNS_LOB_LOC_FIXED_OFFSET
|
|
257
|
+
);
|
|
258
|
+
const fileNameOffset = constants.TNS_LOB_LOC_FIXED_OFFSET + dirNameLen + 4;
|
|
259
|
+
const fileNameLen = this._locator.readUInt16BE(
|
|
260
|
+
dirNameOffset + dirNameLen
|
|
261
|
+
);
|
|
262
|
+
const dirName = this._locator.slice(
|
|
263
|
+
dirNameOffset, dirNameOffset + dirNameLen
|
|
264
|
+
).toString();
|
|
265
|
+
const fileName = this._locator.slice(
|
|
266
|
+
fileNameOffset, fileNameOffset + fileNameLen
|
|
267
|
+
).toString();
|
|
268
|
+
return { dirName: dirName, fileName: fileName };
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
//---------------------------------------------------------------------------
|
|
272
|
+
// checkConn()
|
|
273
|
+
//
|
|
274
|
+
// Internal method to check the connection.
|
|
275
|
+
//---------------------------------------------------------------------------
|
|
158
276
|
checkConn() {
|
|
159
277
|
if (!this.conn.nscon.connected)
|
|
160
278
|
errors.throwErr(errors.ERR_INVALID_CONNECTION);
|
|
161
279
|
}
|
|
162
280
|
|
|
281
|
+
//---------------------------------------------------------------------------
|
|
282
|
+
// close()
|
|
283
|
+
//
|
|
284
|
+
// Internal method to close the LOBs using piggyback mechanism.
|
|
285
|
+
//---------------------------------------------------------------------------
|
|
163
286
|
close() {
|
|
164
287
|
this.checkConn();
|
|
165
288
|
if (this._isTempLob) {
|
|
@@ -169,6 +292,25 @@ class ThinLobImpl extends LobImpl {
|
|
|
169
292
|
}
|
|
170
293
|
}
|
|
171
294
|
|
|
295
|
+
//---------------------------------------------------------------------------
|
|
296
|
+
// closeFile()
|
|
297
|
+
//
|
|
298
|
+
// Internal method to close the opened file for BFILE LOBs.
|
|
299
|
+
//---------------------------------------------------------------------------
|
|
300
|
+
async closeFile() {
|
|
301
|
+
this.checkConn();
|
|
302
|
+
const options = {
|
|
303
|
+
operation: constants.TNS_LOB_OP_FILE_CLOSE,
|
|
304
|
+
sourceLobImpl: this,
|
|
305
|
+
};
|
|
306
|
+
await this._sendMessage(options);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
//---------------------------------------------------------------------------
|
|
310
|
+
// init()
|
|
311
|
+
//
|
|
312
|
+
// Internal method to initialize LOBs.
|
|
313
|
+
//---------------------------------------------------------------------------
|
|
172
314
|
init(conn, locator, dbType, len, chunkSize) {
|
|
173
315
|
this.dirtyLength = false;
|
|
174
316
|
this.conn = conn;
|
|
@@ -184,6 +326,56 @@ class ThinLobImpl extends LobImpl {
|
|
|
184
326
|
this._pieceSize = chunkSize;
|
|
185
327
|
}
|
|
186
328
|
|
|
329
|
+
//---------------------------------------------------------------------------
|
|
330
|
+
// isFileOpen()
|
|
331
|
+
//
|
|
332
|
+
// Internal method to check if the file is already open.
|
|
333
|
+
//---------------------------------------------------------------------------
|
|
334
|
+
async isFileOpen() {
|
|
335
|
+
const options = {
|
|
336
|
+
operation: constants.TNS_LOB_OP_FILE_ISOPEN,
|
|
337
|
+
sourceLobImpl: this
|
|
338
|
+
};
|
|
339
|
+
await this._sendMessage(options);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
//---------------------------------------------------------------------------
|
|
343
|
+
// openFile()
|
|
344
|
+
//
|
|
345
|
+
// Internal method for opening file (BFILE).
|
|
346
|
+
//---------------------------------------------------------------------------
|
|
347
|
+
async openFile() {
|
|
348
|
+
this.checkConn();
|
|
349
|
+
const options = {
|
|
350
|
+
operation: constants.TNS_LOB_OP_FILE_OPEN,
|
|
351
|
+
sourceLobImpl: this,
|
|
352
|
+
amount: constants.TNS_LOB_OPEN_READ_ONLY,
|
|
353
|
+
sendAmount: true
|
|
354
|
+
};
|
|
355
|
+
return await this._sendMessage(options);
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
//---------------------------------------------------------------------------
|
|
359
|
+
// setDirFileName()
|
|
360
|
+
//
|
|
361
|
+
// Internal method for setting the directory alias and name of the file
|
|
362
|
+
// referenced by a BFILE
|
|
363
|
+
//---------------------------------------------------------------------------
|
|
364
|
+
setDirFileName(dirObject) {
|
|
365
|
+
const dirNameLen = Buffer.byteLength(dirObject.dirName);
|
|
366
|
+
const dirNameOffset = constants.TNS_LOB_LOC_FIXED_OFFSET + 2;
|
|
367
|
+
const fileNameOffset = dirNameOffset + dirNameLen + 2;
|
|
368
|
+
const fileNameLen = Buffer.byteLength(dirObject.fileName);
|
|
369
|
+
const newLocLen = fileNameOffset + fileNameLen;
|
|
370
|
+
const newLocator = Buffer.allocUnsafe(newLocLen);
|
|
371
|
+
this._locator.copy(newLocator, 0, 0, constants.TNS_LOB_LOC_FIXED_OFFSET + 1);
|
|
372
|
+
newLocator.writeUInt16BE(dirNameLen, constants.TNS_LOB_LOC_FIXED_OFFSET);
|
|
373
|
+
newLocator.write(dirObject.dirName, dirNameOffset);
|
|
374
|
+
newLocator.writeInt16BE(fileNameLen, dirNameOffset + dirNameLen);
|
|
375
|
+
newLocator.write(dirObject.fileName, fileNameOffset);
|
|
376
|
+
this._locator = newLocator;
|
|
377
|
+
}
|
|
378
|
+
|
|
187
379
|
}
|
|
188
380
|
|
|
189
381
|
module.exports = ThinLobImpl;
|
package/lib/thin/pool.js
CHANGED
|
@@ -64,6 +64,7 @@ class ThinPoolImpl extends PoolImpl {
|
|
|
64
64
|
this._usedConnectionList = new Set();
|
|
65
65
|
this._password = params.password;
|
|
66
66
|
this._walletPassword = params.walletPassword;
|
|
67
|
+
this._walletContent = params.walletContent;
|
|
67
68
|
this._obfuscatedPassword = [];
|
|
68
69
|
this._obfuscatedWalletPassword = [];
|
|
69
70
|
this._token = params.token;
|
|
@@ -88,6 +89,13 @@ class ThinPoolImpl extends PoolImpl {
|
|
|
88
89
|
this._obfuscatedWalletPassword = obj.obfuscatedValue;
|
|
89
90
|
this._userConfig.walletPassword = null;
|
|
90
91
|
}
|
|
92
|
+
// wallet content obfuscation
|
|
93
|
+
if (this._walletContent !== undefined) {
|
|
94
|
+
const obj = protocolUtil.setObfuscatedValue(this._walletContent);
|
|
95
|
+
this._walletContent = obj.value;
|
|
96
|
+
this._obfuscatedWalletContent = obj.obfuscatedValue;
|
|
97
|
+
this._userConfig.walletConent = null;
|
|
98
|
+
}
|
|
91
99
|
// token obfuscation
|
|
92
100
|
if (this._token !== undefined) {
|
|
93
101
|
const obj = protocolUtil.setObfuscatedValue(this._token);
|
|
@@ -172,6 +180,13 @@ class ThinPoolImpl extends PoolImpl {
|
|
|
172
180
|
this._obfuscatedWalletPassword);
|
|
173
181
|
}
|
|
174
182
|
|
|
183
|
+
// deobfuscate wallet content
|
|
184
|
+
if (clonedAttrs.walletContent === null) {
|
|
185
|
+
clonedAttrs.walletContent =
|
|
186
|
+
protocolUtil.getDeobfuscatedValue(this._walletContent,
|
|
187
|
+
this._obfuscatedWalletContent);
|
|
188
|
+
}
|
|
189
|
+
|
|
175
190
|
// deobfuscate token and private key
|
|
176
191
|
// check for token expiry
|
|
177
192
|
if (clonedAttrs.token === null) {
|
|
@@ -118,6 +118,8 @@ class Capabilities {
|
|
|
118
118
|
constants.TNS_CCAP_CTB_IMPLICIT_POOL;
|
|
119
119
|
this.compileCaps[constants.TNS_CCAP_TTC5] =
|
|
120
120
|
constants.TNS_CCAP_VECTOR_SUPPORT;
|
|
121
|
+
this.compileCaps[constants.TNS_CCAP_VECTOR_FEATURES] =
|
|
122
|
+
constants.TNS_CCAP_VECTOR_FEATURE_BINARY;
|
|
121
123
|
}
|
|
122
124
|
|
|
123
125
|
initRuntimeCaps() {
|