oracledb
Advanced tools
Comparing version 6.3.0 to 6.4.0
@@ -66,2 +66,3 @@ # Node-oracledb Examples | ||
[`aqraw.js`](aqraw.js) | Basic Oracle Advanced Queuing (AQ) example passing text messages | ||
[`aqutil.js`](aqutil.js) | Common file to setup the user credentials for all the Advanced Queuing (AQ) examples. | ||
[`blobhttp.js`](blobhttp.js) | Simple web app that streams an image | ||
@@ -116,2 +117,4 @@ [`calltimeout.js`](calltimeout.js) | Shows how to cancel a SQL statement if it doesn't complete in a specified time | ||
[`rowlimit.js`](rowlimit.js) | Shows ways to limit the number of records fetched by queries | ||
[`sampleazuretokenauth.js`](sampleazuretokenauth.js) | Shows connection pooling with Azure token based authentication. | ||
[`sampleocitokenauth.js`](sampleocitokenauth.js) | Shows connection pooling with OCI OAuth 2.0 token based authentication. | ||
[`select1.js`](select1.js) | Executes a basic query without using a connection pool or ResultSet | ||
@@ -118,0 +121,0 @@ [`select2.js`](select2.js) | Executes queries to show array and object output formats |
@@ -1,2 +0,2 @@ | ||
// Copyright (c) 2019, 2023, Oracle and/or its affiliates. | ||
// Copyright (c) 2019, 2024, Oracle and/or its affiliates. | ||
@@ -172,3 +172,3 @@ //----------------------------------------------------------------------------- | ||
1); | ||
const msgImpls = await this._impl.deqMany(maxMessages); | ||
const msgImpls = await this._impl.deq(maxMessages); | ||
return msgImpls.map(i => this._makeMessage(i)); | ||
@@ -184,5 +184,5 @@ } | ||
errors.assertArgCount(arguments, 0, 0); | ||
const msgImpl = await this._impl.deqOne(); | ||
if (msgImpl) | ||
return this._makeMessage(msgImpl); | ||
const msgImpls = await this._impl.deq(1); | ||
if (msgImpls) | ||
return this._makeMessage(msgImpls[0]); | ||
} | ||
@@ -217,3 +217,3 @@ | ||
} | ||
const msgImpls = await this._impl.enqMany(verifiedMessages); | ||
const msgImpls = await this._impl.enq(verifiedMessages); | ||
return msgImpls.map(i => this._makeMessage(i)); | ||
@@ -230,4 +230,4 @@ } | ||
message = this._verifyMessage(message); | ||
const msgImpl = await this._impl.enqOne(message); | ||
return this._makeMessage(msgImpl); | ||
const msgImpls = await this._impl.enq([message]); | ||
return this._makeMessage(msgImpls[0]); | ||
} | ||
@@ -234,0 +234,0 @@ |
@@ -1,2 +0,2 @@ | ||
// Copyright (c) 2016, 2023, Oracle and/or its affiliates. | ||
// Copyright (c) 2016, 2024, Oracle and/or its affiliates. | ||
@@ -46,2 +46,3 @@ //----------------------------------------------------------------------------- | ||
const types = require('./types.js'); | ||
const oson = require('./impl/datahandlers/oson.js'); | ||
@@ -109,3 +110,6 @@ // global mapping of subscriptions; these cannot be tied to a particular | ||
} | ||
nodbUtil.addTypeProperties(objType, "elementType"); | ||
if (objType.isCollection) { | ||
nodbUtil.addTypeProperties(objType, "elementType"); | ||
objType.elementTypeInfo.type = objType.elementType; | ||
} | ||
if (objType.attributes) { | ||
@@ -202,2 +206,5 @@ const props = {}; | ||
Array.isArray(value) || | ||
value instanceof Float32Array || | ||
value instanceof Float64Array || | ||
value instanceof Int8Array || | ||
Buffer.isBuffer(value) || | ||
@@ -840,2 +847,25 @@ util.isDate(value) || | ||
//--------------------------------------------------------------------------- | ||
// decode() | ||
// | ||
// Decodes OSON Buffer to JS data type. | ||
//--------------------------------------------------------------------------- | ||
decodeOSON(buf) { | ||
errors.assertArgCount(arguments, 1, 1); | ||
errors.assertParamValue(Buffer.isBuffer(buf), 1); | ||
const decoder = new oson.OsonDecoder(buf); | ||
return decoder.decode(); | ||
} | ||
//--------------------------------------------------------------------------- | ||
// encode() | ||
// | ||
// Encodes the JS value into OSON bytes. | ||
//--------------------------------------------------------------------------- | ||
encodeOSON(value) { | ||
const encoder = new oson.OsonEncoder(); | ||
return encoder.encode(transformer.transformJsonValue(value)); | ||
} | ||
//--------------------------------------------------------------------------- | ||
// execute() | ||
@@ -851,10 +881,21 @@ // | ||
// process arguments | ||
errors.assertArgCount(arguments, 1, 3); | ||
errors.assertParamValue(typeof sql === 'string', 1); | ||
if (arguments.length >= 2) { | ||
binds = await this._processExecuteBinds(a2); | ||
if (nodbUtil.isObject(sql) && typeof sql.statement === 'string') { | ||
errors.assertArgCount(arguments, 1, 2); | ||
if (sql.values) { | ||
binds = await this._processExecuteBinds(sql.values); | ||
} | ||
sql = sql.statement; | ||
if (arguments.length == 2) { | ||
options = this._verifyExecOpts(a2, false); | ||
} | ||
} else { | ||
errors.assertArgCount(arguments, 1, 3); | ||
errors.assertParamValue(typeof sql === 'string', 1); | ||
if (arguments.length >= 2) { | ||
binds = await this._processExecuteBinds(a2); | ||
} | ||
if (arguments.length == 3) { | ||
options = this._verifyExecOpts(a3, false); | ||
} | ||
} | ||
if (arguments.length == 3) { | ||
options = this._verifyExecOpts(a3, false); | ||
} | ||
this._addDefaultsToExecOpts(options); | ||
@@ -954,2 +995,7 @@ errors.assert(this._impl, errors.ERR_INVALID_CONNECTION); | ||
// convert ORA warnings to NJS | ||
if (result.warning) { | ||
result.warning = errors.transformErr(result.warning); | ||
} | ||
// process output binds | ||
@@ -956,0 +1002,0 @@ if (result.outBinds !== undefined) { |
@@ -1,2 +0,2 @@ | ||
// Copyright (c) 2022, 2023, Oracle and/or its affiliates. | ||
// Copyright (c) 2022, 2024, Oracle and/or its affiliates. | ||
@@ -203,2 +203,8 @@ //----------------------------------------------------------------------------- | ||
TPC_END_SUSPEND: 0x00100000, | ||
// vector types | ||
VECTOR_FORMAT_FLOAT32: 2, | ||
VECTOR_FORMAT_FLOAT64: 3, | ||
VECTOR_FORMAT_INT8: 4, | ||
}; |
@@ -1,2 +0,2 @@ | ||
// Copyright (c) 2019, 2023, Oracle and/or its affiliates. | ||
// Copyright (c) 2019, 2024, Oracle and/or its affiliates. | ||
@@ -35,2 +35,44 @@ //---------------------------------------------------------------------------- | ||
//--------------------------------------------------------------------------- | ||
// validatePropertyValue | ||
// | ||
// Validate the value based on metadata. | ||
// For object type, metaData corresponds to the attribute which is set. | ||
// For collection type, metaData corresponds to element in the collection. | ||
//--------------------------------------------------------------------------- | ||
function validatePropertyValue(objType, metaData, value, index) { | ||
let valueLen, lengthErr = false; | ||
if (value) { | ||
switch (metaData.type) { | ||
case types.DB_TYPE_VARCHAR: | ||
case types.DB_TYPE_NVARCHAR: | ||
case types.DB_TYPE_NCHAR: | ||
case types.DB_TYPE_CHAR: | ||
valueLen = Buffer.byteLength(value); | ||
if (valueLen > metaData.maxSize) { | ||
lengthErr = true; | ||
} | ||
break; | ||
case types.DB_TYPE_RAW: | ||
valueLen = value.length; | ||
if (valueLen > metaData.maxSize) { | ||
lengthErr = true; | ||
} | ||
break; | ||
default: | ||
break; | ||
} | ||
if (lengthErr) { | ||
if (index !== undefined) { | ||
errors.throwErr(errors.ERR_WRONG_LENGTH_FOR_DBOBJECT_ELEM, | ||
index, objType.fqn, valueLen, metaData.maxSize); | ||
} else { | ||
errors.throwErr(errors.ERR_WRONG_LENGTH_FOR_DBOBJECT_ATTR, | ||
metaData.name, objType.fqn, valueLen, metaData.maxSize); | ||
} | ||
} | ||
} | ||
} | ||
// define base database object class; instances of this class are never | ||
@@ -65,2 +107,3 @@ // instantiated; instead, classes subclassed from this one will be | ||
value = transformer.transformValueIn(info, value, options); | ||
validatePropertyValue(this._objType, attr, value); | ||
this._impl.setAttrValue(attr, value); | ||
@@ -129,2 +172,9 @@ } | ||
value = transformer.transformValueIn(info, value, options); | ||
let index = this._impl.getLastIndex(); | ||
if (index) { | ||
index = index + 1; // element will be appended at index + 1. | ||
} else { | ||
index = 0; // undefined for initial append, so set it to 0 | ||
} | ||
validatePropertyValue(this._objType, this._objType.elementTypeInfo, value, index); | ||
this._impl.append(value); | ||
@@ -350,2 +400,3 @@ } | ||
value = transformer.transformValueIn(info, value, options); | ||
validatePropertyValue(this._objType, this._objType.elementTypeInfo, value, index); | ||
this._impl.setElement(index, value); | ||
@@ -395,2 +446,21 @@ } | ||
//--------------------------------------------------------------------------- | ||
// toMap() | ||
// | ||
// Returns the Map object where the collection’s indexes are the keys and | ||
// the elements are its values. | ||
//--------------------------------------------------------------------------- | ||
toMap() { | ||
errors.assertArgCount(arguments, 0, 0); | ||
if (!this.isCollection) { | ||
errors.throwErr(errors.ERR_OBJECT_IS_NOT_A_COLLECTION, | ||
this.name); | ||
} | ||
const result = new Map(); | ||
this.getKeys().forEach(element => { | ||
result.set(element, this.getElement(element)); | ||
}); | ||
return result; | ||
} | ||
} | ||
@@ -429,2 +499,3 @@ | ||
"getValues", | ||
"toMap", | ||
"hasElement", | ||
@@ -431,0 +502,0 @@ "setElement", |
@@ -1,2 +0,2 @@ | ||
// Copyright (c) 2022, 2023, Oracle and/or its affiliates. | ||
// Copyright (c) 2022, 2024, Oracle and/or its affiliates. | ||
@@ -110,3 +110,2 @@ //----------------------------------------------------------------------------- | ||
const ERR_INVALID_REF_CURSOR = 107; | ||
const ERR_LOB_CLOSED = 108; | ||
const ERR_INVALID_TYPE_NUM = 109; | ||
@@ -142,2 +141,8 @@ const ERR_INVALID_ORACLE_TYPE_NUM = 110; | ||
const ERR_WRONG_USER_FORMAT_EXTAUTH_PROXY = 140; | ||
const ERR_TOO_MANY_BATCH_ERRORS = 141; | ||
const ERR_WRONG_LENGTH_FOR_DBOBJECT_ATTR = 142; | ||
const ERR_WRONG_LENGTH_FOR_DBOBJECT_ELEM = 143; | ||
const ERR_VECTOR_FORMAT_NOT_SUPPORTED = 144; | ||
const ERR_VECTOR_VERSION_NOT_SUPPORTED = 145; | ||
const ERR_OBJECT_IS_NOT_A_COLLECTION = 146; | ||
@@ -173,5 +178,4 @@ // Oracle Net layer errors start from 500 | ||
const adjustErrorXref = new Map(); | ||
adjustErrorXref.set("DPI-1010", ERR_CONNECTION_CLOSED); | ||
adjustErrorXref.set("DPI-1010", ERR_INVALID_CONNECTION); | ||
adjustErrorXref.set("DPI-1024", [ERR_INVALID_COLL_INDEX_GET, 'at index ([0-9]+) does']); | ||
adjustErrorXref.set("DPI-1040", ERR_LOB_CLOSED); | ||
adjustErrorXref.set("DPI-1044", ERR_ORACLE_NUMBER_NO_REPR); | ||
@@ -196,3 +200,3 @@ adjustErrorXref.set("DPI-1055", ERR_NAN_VALUE); | ||
messages.set(ERR_INVALID_CONNECTION, // NJS-003 | ||
'invalid connection'); | ||
'invalid or closed connection'); | ||
messages.set(ERR_INVALID_PROPERTY_VALUE, // NJS-004 | ||
@@ -348,4 +352,2 @@ 'invalid value for property "%s"'); | ||
'invalid cursor'); | ||
messages.set(ERR_LOB_CLOSED, // NJS-108 | ||
'LOB was already closed'); | ||
messages.set(ERR_INVALID_TYPE_NUM, // NJS-109 | ||
@@ -411,2 +413,14 @@ 'invalid type number %d'); | ||
'user name must be enclosed in [] when using external authentication with a proxy user'); | ||
messages.set(ERR_TOO_MANY_BATCH_ERRORS, // NJS-141 | ||
'the number of batch errors from executemany() exceeds 65535'); | ||
messages.set(ERR_WRONG_LENGTH_FOR_DBOBJECT_ATTR, // NJS-142 | ||
'value too large for attribute %s of object %s (actual: %d, maximum: %d)'); | ||
messages.set(ERR_WRONG_LENGTH_FOR_DBOBJECT_ELEM, // NJS-143 | ||
'value too large for element %d of object %s (actual: %d, maximum: %d)'); | ||
messages.set(ERR_VECTOR_FORMAT_NOT_SUPPORTED, // NJS-144 | ||
'VECTOR format %d is not supported'); | ||
messages.set(ERR_VECTOR_VERSION_NOT_SUPPORTED, // NJS-145 | ||
'VECTOR version %d is not supported'); | ||
messages.set(ERR_OBJECT_IS_NOT_A_COLLECTION, // NJS-146 | ||
'object %s is not a collection'); | ||
@@ -765,3 +779,2 @@ // Oracle Net layer errors | ||
ERR_NAN_VALUE, | ||
ERR_LOB_CLOSED, | ||
ERR_ORACLE_NUMBER_NO_REPR, | ||
@@ -799,2 +812,8 @@ ERR_INVALID_SERVICE_NAME, | ||
ERR_WRONG_USER_FORMAT_EXTAUTH_PROXY, | ||
ERR_TOO_MANY_BATCH_ERRORS, | ||
ERR_WRONG_LENGTH_FOR_DBOBJECT_ATTR, | ||
ERR_WRONG_LENGTH_FOR_DBOBJECT_ELEM, | ||
ERR_VECTOR_FORMAT_NOT_SUPPORTED, | ||
ERR_VECTOR_VERSION_NOT_SUPPORTED, | ||
ERR_OBJECT_IS_NOT_A_COLLECTION, | ||
ERR_CONNECTION_CLOSED_CODE: `${ERR_PREFIX}-${ERR_CONNECTION_CLOSED}`, | ||
@@ -801,0 +820,0 @@ WRN_COMPILATION_CREATE, |
@@ -151,2 +151,11 @@ // Copyright (c) 2022, Oracle and/or its affiliates. | ||
//--------------------------------------------------------------------------- | ||
// getPoolPingTimeout() | ||
// | ||
// Returns the pool ping Timeout (milliseconds). | ||
//--------------------------------------------------------------------------- | ||
getPoolPingTimeout() { | ||
errors.throwNotImplemented("getting the pool ping Timeout"); | ||
} | ||
//--------------------------------------------------------------------------- | ||
// getPoolTimeout() | ||
@@ -153,0 +162,0 @@ // |
@@ -36,2 +36,3 @@ // Copyright (c) 2022, 2023, Oracle and/or its affiliates. | ||
const Lob = require('../lob.js'); | ||
const oson = require('./datahandlers/oson.js'); | ||
@@ -109,22 +110,38 @@ // define implementation class | ||
// If IsJson is set convert to JSON objects unless | ||
// If IsJson or IsOson is set, convert to JSON objects unless | ||
// user defined output type handler overwrites it. | ||
if (future.oldJsonColumnAsObj && metadata.isJson && metadata.dbType !== types.DB_TYPE_JSON | ||
if (metadata.dbType !== types.DB_TYPE_JSON && future.oldJsonColumnAsObj | ||
&& userConverter === undefined) { | ||
const outConverter = async function(val) { | ||
if (!val) { | ||
return val; | ||
} | ||
let outConverter; | ||
if (metadata.isOson) { | ||
outConverter = async function(val) { | ||
if (!val) { | ||
return val; | ||
} | ||
let result = val; | ||
if (val instanceof Lob) { | ||
result = await val.getData(); | ||
} | ||
const decoder = new oson.OsonDecoder(result); | ||
return decoder.decode(); | ||
}; | ||
converter = outConverter; | ||
} else if (metadata.isJson) { | ||
outConverter = async function(val) { | ||
if (!val) { | ||
return val; | ||
} | ||
let result = val; | ||
if (val instanceof Lob) { | ||
result = await val.getData(); | ||
} | ||
if (result instanceof Buffer) { | ||
result = result.toString(); | ||
} | ||
result = JSON.parse(result); | ||
return result; | ||
}; | ||
converter = outConverter; | ||
let result = val; | ||
if (val instanceof Lob) { | ||
result = await val.getData(); | ||
} | ||
if (result instanceof Buffer) { | ||
result = result.toString(); | ||
} | ||
result = JSON.parse(result); | ||
return result; | ||
}; | ||
converter = outConverter; | ||
} | ||
} | ||
@@ -131,0 +148,0 @@ |
@@ -1,2 +0,2 @@ | ||
// Copyright (c) 2016, 2023, Oracle and/or its affiliates. | ||
// Copyright (c) 2016, 2024, Oracle and/or its affiliates. | ||
@@ -53,3 +53,3 @@ //----------------------------------------------------------------------------- | ||
// if LOB was already closed, nothing to do! | ||
if (err && err.message.startsWith("NJS-108:")) | ||
if (err && err.message.startsWith("NJS-003:")) | ||
delete this._impl; | ||
@@ -189,8 +189,24 @@ if (this._impl) { | ||
// | ||
// Returns all of the data in the LOB as a single string or buffer. | ||
// Return a portion (or all) of the data in the LOB. Note that the amount | ||
// and offset are in bytes for BLOB and BFILE type LOBs and in UCS - 2 code | ||
// points for CLOB and NCLOB type LOBs.UCS-2 code points are equivalent | ||
// to characters for all but supplemental characters.If supplemental | ||
// characters are in the LOB, the offset and amount will have to be chosen | ||
// carefully to avoid splitting a character. | ||
// Returns data in the LOB as a single string or buffer. | ||
//--------------------------------------------------------------------------- | ||
async getData() { | ||
errors.assertArgCount(arguments, 0, 0); | ||
async getData(offset, amount) { | ||
errors.assertArgCount(arguments, 0, 2); | ||
if (offset === undefined) { | ||
offset = 1; | ||
} else { | ||
errors.assertParamValue(Number.isInteger(offset) && offset > 0, 1); | ||
} | ||
if (amount === undefined) { | ||
amount = 0; | ||
} else { | ||
errors.assertParamValue(Number.isInteger(amount) && amount > 0, 2); | ||
} | ||
errors.assert(this._impl, errors.ERR_INVALID_LOB); | ||
return await this._impl.getData(); | ||
return await this._impl.getData(offset, amount); | ||
} | ||
@@ -197,0 +213,0 @@ |
@@ -371,2 +371,9 @@ // Copyright (c) 2015, 2023, Oracle and/or its affiliates. | ||
// poolPingTimeout must be an integer (>= 0) | ||
if (options.poolPingTimeout !== undefined) { | ||
errors.assertParamPropValue(Number.isInteger(options.poolPingTimeout) && | ||
options.poolPingTimeout >= 0, 1, "poolPingTimeout"); | ||
outOptions.poolPingTimeout = options.poolPingTimeout; | ||
} | ||
// homogeneous must be a boolean (and defaults to True) | ||
@@ -562,2 +569,3 @@ outOptions.homogeneous = true; | ||
"poolPingInterval", | ||
"poolPingTimeout", | ||
"queueMax", | ||
@@ -885,2 +893,3 @@ "queueTimeout"); | ||
DB_TYPE_XMLTYPE: types.DB_TYPE_XMLTYPE, | ||
DB_TYPE_VECTOR: types.DB_TYPE_VECTOR, | ||
@@ -1017,2 +1026,7 @@ // fetchInfo type defaulting | ||
// vector types | ||
VECTOR_FORMAT_FLOAT32: constants.VECTOR_FORMAT_FLOAT32, | ||
VECTOR_FORMAT_FLOAT64: constants.VECTOR_FORMAT_FLOAT64, | ||
VECTOR_FORMAT_INT8: constants.VECTOR_FORMAT_INT8, | ||
// database type aliases | ||
@@ -1120,2 +1134,6 @@ BLOB: types.DB_TYPE_BLOB, | ||
get poolPingTimeout() { | ||
return settings.poolPingTimeout; | ||
}, | ||
get poolTimeout() { | ||
@@ -1259,2 +1277,8 @@ return settings.poolTimeout; | ||
set poolPingTimeout(value) { | ||
errors.assertPropValue(Number.isInteger(value) && value >= 0, | ||
"poolPingTimeout"); | ||
settings.poolPingTimeout = value; | ||
}, | ||
set poolTimeout(value) { | ||
@@ -1261,0 +1285,0 @@ errors.assertPropValue(Number.isInteger(value) && value >= 0, |
@@ -1,2 +0,2 @@ | ||
// Copyright (c) 2016, 2022, Oracle and/or its affiliates. | ||
// Copyright (c) 2016, 2024, Oracle and/or its affiliates. | ||
@@ -632,2 +632,11 @@ //----------------------------------------------------------------------------- | ||
//--------------------------------------------------------------------------- | ||
// poolPingTimeout | ||
// | ||
// Property for the ping timeout associated with the pool. | ||
//--------------------------------------------------------------------------- | ||
get poolPingTimeout() { | ||
return this._impl.getPoolPingTimeout(); | ||
} | ||
//--------------------------------------------------------------------------- | ||
// poolTimeout | ||
@@ -634,0 +643,0 @@ // |
@@ -1,2 +0,2 @@ | ||
// Copyright (c) 2021, 2023, Oracle and/or its affiliates. | ||
// Copyright (c) 2021, 2024, Oracle and/or its affiliates. | ||
@@ -75,2 +75,3 @@ //----------------------------------------------------------------------------- | ||
this.poolPingInterval = pool.poolPingInterval; | ||
this.poolPingTimeout = pool.poolPingTimeout; | ||
this.poolTimeout = pool.poolTimeout; | ||
@@ -128,2 +129,3 @@ this.queueMax = pool.queueMax; | ||
console.log('...poolPingInterval (seconds):', this.poolPingInterval); | ||
console.log('...poolPingTimeout (milliseconds):', this.poolPingTimeout); | ||
console.log('...poolTimeout (seconds):', this.poolTimeout); | ||
@@ -130,0 +132,0 @@ console.log('...queueMax:', this.queueMax); |
@@ -1,2 +0,2 @@ | ||
// Copyright (c) 2022, 2023, Oracle and/or its affiliates. | ||
// Copyright (c) 2022, 2024, Oracle and/or its affiliates. | ||
@@ -32,2 +32,4 @@ //----------------------------------------------------------------------------- | ||
const types = require('./types.js'); | ||
const nodbUtil = require("./util.js"); | ||
const vector = require('./impl/datahandlers/vector.js'); | ||
@@ -55,2 +57,3 @@ class Settings { | ||
this.poolPingInterval = 60; | ||
this.poolPingTimeout = 5000; | ||
this.poolTimeout = 60; | ||
@@ -110,10 +113,28 @@ this.prefetchRows = 2; | ||
_makeDate(useLocal, year, month, day, hour, minute, second, fseconds, offset) { | ||
if (useLocal) { | ||
return new Date(year, month - 1, day, hour, minute, second, fseconds); | ||
} | ||
return new Date(Date.UTC(year, month - 1, day, hour, minute, second, | ||
fseconds) - offset * 60000); | ||
return nodbUtil.makeDate(useLocal, year, month, day, hour, minute, second, fseconds, offset); | ||
} | ||
//--------------------------------------------------------------------------- | ||
// _decodeVector() | ||
// | ||
// Returns a typed array by decoding buffer. | ||
// | ||
//--------------------------------------------------------------------------- | ||
_decodeVector(buffer) { | ||
const decoder = new vector.VectorDecoder(buffer); | ||
return decoder.decode(); | ||
} | ||
//--------------------------------------------------------------------------- | ||
// _encodeVector() | ||
// | ||
// Create a Vector image from typedarray | ||
// | ||
//--------------------------------------------------------------------------- | ||
_encodeVector(value) { | ||
const encoder = new vector.VectorEncoder(); | ||
return encoder.encode(value); | ||
} | ||
//--------------------------------------------------------------------------- | ||
// addToOptions() | ||
@@ -165,2 +186,5 @@ // | ||
break; | ||
case types.DB_TYPE_VECTOR: | ||
map.set(types.DB_TYPE_VECTOR, types.DB_TYPE_LONG); | ||
break; | ||
case types.DB_TYPE_RAW: | ||
@@ -167,0 +191,0 @@ map.set(types.DB_TYPE_RAW, types.DB_TYPE_VARCHAR); |
@@ -1,2 +0,2 @@ | ||
// Copyright (c) 2018, 2023, Oracle and/or its affiliates. | ||
// Copyright (c) 2018, 2024, Oracle and/or its affiliates. | ||
@@ -63,2 +63,15 @@ //----------------------------------------------------------------------------- | ||
[Symbol.asyncIterator]() { | ||
const cursor = this; | ||
return { | ||
async next() { | ||
const doc = await cursor.getNext(); | ||
return {value: doc, done: doc === undefined}; | ||
}, | ||
return() { | ||
return {done: true}; | ||
} | ||
}; | ||
} | ||
} | ||
@@ -65,0 +78,0 @@ |
@@ -1,2 +0,2 @@ | ||
// Copyright (c) 2022, 2023, Oracle and/or its affiliates. | ||
// Copyright (c) 2022, 2024, Oracle and/or its affiliates. | ||
@@ -34,3 +34,3 @@ //----------------------------------------------------------------------------- | ||
const Protocol = require("./protocol/protocol.js"); | ||
const { BaseBuffer } = require('./protocol/buffer.js'); | ||
const { BaseBuffer } = require('../impl/datahandlers/buffer.js'); | ||
const {NetworkSession: nsi} = require("./sqlnet/networkSession.js"); | ||
@@ -45,2 +45,3 @@ const { Statement } = require("./statement"); | ||
const messages = require('./protocol/messages'); | ||
const StatementCache = require('./statementCache.js'); | ||
@@ -68,3 +69,2 @@ const finalizationRegistry = new global.FinalizationRegistry((heldValue) => { | ||
} | ||
this._protocol.callTimeout = 0; // not applicable for close | ||
if (this._drcpEnabled) { | ||
@@ -74,3 +74,2 @@ await this._sessRelease(); | ||
} | ||
if (this._pool && !this._dropSess) { | ||
@@ -101,9 +100,9 @@ await this._pool.release(this); | ||
//--------------------------------------------------------------------------- | ||
// _determineElementObjType() | ||
// _getElementTypeObj() | ||
// | ||
// Determine the element type's object type. This is needed when processing | ||
// Get the element type's object type. This is needed when processing | ||
// collections with an object as the element type since this information is | ||
// not available in the TDS. | ||
//--------------------------------------------------------------------------- | ||
async _determineElementObjType(info) { | ||
async _getElementTypeObj(info) { | ||
const binds = [ | ||
@@ -263,56 +262,73 @@ { | ||
//--------------------------------------------------------------------------- | ||
// _parseElementType() | ||
// _parseTDSAttr() | ||
// | ||
// Parses the element type from the TDS buffer. | ||
// Returns the DB type and fills metadata from the TDS buffer. | ||
//--------------------------------------------------------------------------- | ||
async _parseElementType(buf, info) { | ||
let oraTypeNum, csfrm; | ||
const attrType = buf.readUInt8(); | ||
_parseTDSAttr(buf, metaData) { | ||
let oraTypeNum, csfrm, attrType; | ||
// skip until a type code that is of interest | ||
for (;;) { | ||
attrType = buf.readUInt8(); | ||
if (attrType === constants.TNS_OBJ_TDS_TYPE_EMBED_ADT_INFO) { | ||
buf.skipBytes(1); // flags | ||
} else if (attrType !== constants.TNS_OBJ_TDS_TYPE_SUBTYPE_MARKER) { | ||
break; | ||
} | ||
} | ||
// process the type code. | ||
switch (attrType) { | ||
case constants.TNS_OBJ_TDS_TYPE_NUMBER: | ||
metaData.precision = buf.readInt8(); | ||
metaData.scale = buf.readInt8(); | ||
return types.DB_TYPE_NUMBER; | ||
case constants.TNS_OBJ_TDS_TYPE_FLOAT: | ||
info.elementType = types.DB_TYPE_NUMBER; | ||
break; | ||
metaData.precision = buf.readInt8(); | ||
return types.DB_TYPE_NUMBER; | ||
case constants.TNS_OBJ_TDS_TYPE_VARCHAR: | ||
case constants.TNS_OBJ_TDS_TYPE_CHAR: | ||
info.maxSize = buf.readUInt16BE(); | ||
metaData.maxSize = buf.readUInt16BE(); // maximum length | ||
oraTypeNum = (attrType === constants.TNS_OBJ_TDS_TYPE_VARCHAR) ? | ||
constants.TNS_DATA_TYPE_VARCHAR : constants.TNS_DATA_TYPE_CHAR; | ||
csfrm = buf.readUInt8(); | ||
info.elementType = types.getTypeByOraTypeNum(oraTypeNum, csfrm); | ||
break; | ||
csfrm = csfrm & 0x7f; | ||
buf.skipBytes(2); // character set | ||
return types.getTypeByOraTypeNum(oraTypeNum, csfrm); | ||
case constants.TNS_OBJ_TDS_TYPE_RAW: | ||
info.elementType = types.DB_TYPE_RAW; | ||
break; | ||
metaData.maxSize = buf.readUInt16BE(); // maximum length | ||
return types.DB_TYPE_RAW; | ||
case constants.TNS_OBJ_TDS_TYPE_BINARY_FLOAT: | ||
info.elementType = types.DB_TYPE_BINARY_FLOAT; | ||
break; | ||
return types.DB_TYPE_BINARY_FLOAT; | ||
case constants.TNS_OBJ_TDS_TYPE_BINARY_DOUBLE: | ||
info.elementType = types.DB_TYPE_BINARY_DOUBLE; | ||
break; | ||
return types.DB_TYPE_BINARY_DOUBLE; | ||
case constants.TNS_OBJ_TDS_TYPE_DATE: | ||
info.elementType = types.DB_TYPE_DATE; | ||
break; | ||
return types.DB_TYPE_DATE; | ||
case constants.TNS_OBJ_TDS_TYPE_TIMESTAMP: | ||
info.elementType = types.DB_TYPE_TIMESTAMP; | ||
break; | ||
buf.skipBytes(1); // precision | ||
return types.DB_TYPE_TIMESTAMP; | ||
case constants.TNS_OBJ_TDS_TYPE_TIMESTAMP_LTZ: | ||
info.elementType = types.DB_TYPE_TIMESTAMP_LTZ; | ||
break; | ||
buf.skipBytes(1); // precision | ||
return types.DB_TYPE_TIMESTAMP_LTZ; | ||
case constants.TNS_OBJ_TDS_TYPE_TIMESTAMP_TZ: | ||
info.elementType = types.DB_TYPE_TIMESTAMP_TZ; | ||
break; | ||
buf.skipBytes(1); // precision | ||
return types.DB_TYPE_TIMESTAMP_TZ; | ||
case constants.TNS_OBJ_TDS_TYPE_BOOLEAN: | ||
info.elementType = types.DB_TYPE_BOOLEAN; | ||
break; | ||
return types.DB_TYPE_BOOLEAN; | ||
case constants.TNS_OBJ_TDS_TYPE_CLOB: | ||
this._determineElementTypeCharsetForm(info); | ||
break; | ||
return types.DB_TYPE_CLOB; | ||
case constants.TNS_OBJ_TDS_TYPE_BLOB: | ||
info.elementType = types.DB_TYPE_BLOB; | ||
break; | ||
return types.DB_TYPE_BLOB; | ||
case constants.TNS_OBJ_TDS_TYPE_OBJ: | ||
info.elementType = types.DB_TYPE_OBJECT; | ||
await this._determineElementObjType(info); | ||
break; | ||
buf.skipBytes(5); | ||
return types.DB_TYPE_OBJECT; | ||
case constants.TNS_OBJ_TDS_TYPE_START_EMBED_ADT: | ||
// loop until end type, TNS_OBJ_TDS_TYPE_END_EMBED_ADT | ||
// is received. | ||
while (this._parseTDSAttr(buf, {}) !== 0) { | ||
continue; | ||
} | ||
return types.DB_TYPE_OBJECT; | ||
case constants.TNS_OBJ_TDS_TYPE_END_EMBED_ADT: | ||
return 0; | ||
default: | ||
@@ -326,8 +342,5 @@ errors.throwErr(errors.ERR_TDS_TYPE_NOT_SUPPORTED, attrType); | ||
// | ||
// Parses the TDS for the type. This is only needed for collection types, so | ||
// if the TDS is determined to be for an object type, the remaining | ||
// information is ignored. | ||
// Parses the TDS (type descriptor segment) for the type. | ||
//--------------------------------------------------------------------------- | ||
async _parseTDS(tds, info) { | ||
// parse initial TDS bytes | ||
@@ -342,6 +355,2 @@ const buf = new TDSBuffer(tds); | ||
const numAttrs = buf.readUInt16BE(); | ||
if (numAttrs > 1) { | ||
info.isCollection = false; | ||
return; | ||
} | ||
@@ -354,19 +363,37 @@ // continue parsing TDS bytes to discover if type refers to a collection | ||
// if type of first attribute is not a collection, nothing further needs | ||
// to be done | ||
const attrType = buf.readUInt8(); | ||
info.isCollection = (attrType === constants.TNS_OBJ_TDS_TYPE_COLL); | ||
if (!info.isCollection) | ||
return; | ||
// check to see if type refers to a collection (only one attribute is | ||
// present in that case). | ||
info.isCollection = false; | ||
if (numAttrs === 1) { | ||
const pos = buf.pos; | ||
const attrType = buf.readUInt8(); | ||
if (attrType === constants.TNS_OBJ_TDS_TYPE_COLL) { | ||
info.isCollection = true; | ||
} else { | ||
buf.pos = pos; | ||
} | ||
} | ||
// continue parsing TDS to determine element type | ||
const elementPos = buf.readUInt32BE(); | ||
info.maxNumElements = buf.readUInt32BE(); | ||
info.collectionType = buf.readUInt8(); | ||
if (info.collectionType === constants.TNS_OBJ_PLSQL_INDEX_TABLE) { | ||
info.collectionFlags = constants.TNS_OBJ_HAS_INDEXES; | ||
// Handle collections | ||
if (info.isCollection) { | ||
// continue parsing TDS to determine element type | ||
const elementPos = buf.readUInt32BE(); | ||
info.maxNumElements = buf.readUInt32BE(); | ||
info.collectionType = buf.readUInt8(); | ||
if (info.collectionType === constants.TNS_OBJ_PLSQL_INDEX_TABLE) { | ||
info.collectionFlags = constants.TNS_OBJ_HAS_INDEXES; | ||
} | ||
buf.pos = elementPos; | ||
info.elementTypeInfo = {}; | ||
info.elementType = this._parseTDSAttr(buf, info.elementTypeInfo); | ||
if (info.elementType === types.DB_TYPE_OBJECT) { | ||
await this._getElementTypeObj(info); | ||
} | ||
} else { | ||
if (info.attributes) { // skip for XML type as it has no attributes. | ||
for (const attr of info.attributes) { | ||
this._parseTDSAttr(buf, attr); | ||
} | ||
} | ||
} | ||
buf.pos = elementPos; | ||
await this._parseElementType(buf, info); | ||
} | ||
@@ -497,5 +524,5 @@ | ||
info.version = result.outBinds.version; | ||
await this._parseTDS(result.outBinds.tds, info); | ||
const attrRows = await result.outBinds.attrs_rc.getRows(1000, {}); | ||
if (attrRows.length > 0) { | ||
// Its an object not a collection. | ||
info.attributes = []; | ||
@@ -516,4 +543,5 @@ for (const row of attrRows) { | ||
} | ||
await this._parseTDS(result.outBinds.tds, info); | ||
info.partial = false; | ||
return info; | ||
@@ -613,7 +641,4 @@ | ||
this.invokeSessionCallback = true; | ||
this.statementCache = new Map(); | ||
this.statementCacheSize = params.stmtCacheSize; | ||
this._numCursorsToClose = 0; | ||
this._currentSchemaModified = false; | ||
this._cursorsToClose = new Set(); | ||
this._tempLobsToClose = []; | ||
@@ -722,2 +747,3 @@ this._tempLobsTotalSize = 0; | ||
this.statementCache = new StatementCache(this.statementCacheSize); | ||
// maintain a list of partially populated database object types | ||
@@ -735,50 +761,9 @@ this._partialDbObjectTypes = []; | ||
//--------------------------------------------------------------------------- | ||
// Sets that a statement is no longer in use | ||
// Return the statement to the statement cache, if applicable | ||
//--------------------------------------------------------------------------- | ||
_returnStatement(statement) { | ||
if (statement.bindInfoList) { | ||
statement.bindInfoList.forEach(bindInfo => { | ||
bindInfo.bindVar = null; | ||
}); | ||
} | ||
if (statement.queryVars) { | ||
statement.queryVars.forEach(queryVar => { | ||
queryVar.values.fill(null); | ||
}); | ||
} | ||
if (statement.returnToCache) { | ||
statement.inUse = false; | ||
} else if (statement.cursorId !== 0) { | ||
this._addCursorToClose(statement.cursorId); | ||
} | ||
this.statementCache.returnStatement(statement); | ||
} | ||
//--------------------------------------------------------------------------- | ||
// Adds the cursors that needs to be closed to the _cursorsToClose set | ||
//--------------------------------------------------------------------------- | ||
_addCursorToClose(cursorId) { | ||
if (this._cursorsToClose.has(cursorId)) { | ||
const reason = `attempt to close cursor ${cursorId} twice`; | ||
errors.throwErr(errors.ERR_INTERNAL, reason); | ||
} | ||
this._cursorsToClose.add(cursorId); | ||
} | ||
//--------------------------------------------------------------------------- | ||
// Adjusts the statement cache to remove least recently used statements | ||
//--------------------------------------------------------------------------- | ||
_adjustStatementCache() { | ||
while (this.statementCache.size > this.statementCacheSize) { | ||
const sql = this.statementCache.keys().next().value; | ||
const stmt = this.statementCache.get(sql); | ||
this.statementCache.delete(sql); | ||
if (stmt.inUse) { | ||
stmt.returnToCache = false; | ||
} else if (stmt.cursorId !== 0) { | ||
this._addCursorToClose(stmt.cursorId); | ||
} | ||
} | ||
} | ||
//--------------------------------------------------------------------------- | ||
// Parses the sql statement and puts it into cache if keepInStmtCache | ||
@@ -891,10 +876,2 @@ // option is true | ||
//--------------------------------------------------------------------------- | ||
// Clears the statement cache for the connection | ||
//--------------------------------------------------------------------------- | ||
resetStatementCache() { | ||
this.statementCache.clear(); | ||
this._cursorsToClose.clear(); | ||
} | ||
//--------------------------------------------------------------------------- | ||
// getDbObjectClass() | ||
@@ -963,27 +940,6 @@ // | ||
_getStatement(sql, cacheStatement = false) { | ||
let statement = this.statementCache.get(sql); | ||
if (!statement) { | ||
statement = new Statement(); | ||
statement._prepare(sql); | ||
if (cacheStatement && !this._drcpEstablishSession && !statement.isDdl && | ||
this.statementCacheSize > 0) { | ||
statement.returnToCache = true; | ||
this.statementCache.set(sql, statement); | ||
this._adjustStatementCache(); | ||
} | ||
} else if (statement.inUse || !cacheStatement || | ||
this._drcpEstablishSession) { | ||
if (!cacheStatement) { | ||
this.statementCache.delete(sql); | ||
statement.returnToCache = false; | ||
} | ||
if (statement.inUse || this._drcpEstablishSession) { | ||
statement = statement._copy(); | ||
} | ||
} else { | ||
this.statementCache.delete(sql); | ||
this.statementCache.set(sql, statement); | ||
if (this._drcpEstablishSession) { | ||
cacheStatement = false; | ||
} | ||
statement.inUse = true; | ||
return statement; | ||
return this.statementCache.getStatement(sql, cacheStatement); | ||
} | ||
@@ -1083,3 +1039,3 @@ | ||
getStmtCacheSize() { | ||
return this.statementCacheSize; | ||
return this.statementCache._maxSize; | ||
} | ||
@@ -1086,0 +1042,0 @@ |
@@ -1,2 +0,2 @@ | ||
// Copyright (c) 2023, Oracle and/or its affiliates. | ||
// Copyright (c) 2023, 2024, Oracle and/or its affiliates. | ||
@@ -34,3 +34,3 @@ //----------------------------------------------------------------------------- | ||
const DbObjectImpl = require('../impl/dbObject.js'); | ||
const { GrowableBuffer } = require('./protocol/buffer.js'); | ||
const { GrowableBuffer } = require('../impl/datahandlers/buffer.js'); | ||
const ThinLobImpl = require('./lob.js'); | ||
@@ -284,5 +284,7 @@ | ||
case types.DB_TYPE_BINARY_DOUBLE: | ||
buf.writeUInt8(8); | ||
buf.writeBinaryDouble(value); | ||
break; | ||
case types.DB_TYPE_BINARY_FLOAT: | ||
buf.writeUInt8(4); | ||
buf.writeBinaryFloat(value); | ||
@@ -289,0 +291,0 @@ break; |
@@ -1,2 +0,2 @@ | ||
// Copyright (c) 2022, 2023, Oracle and/or its affiliates. | ||
// Copyright (c) 2022, 2024, Oracle and/or its affiliates. | ||
@@ -92,7 +92,7 @@ //----------------------------------------------------------------------------- | ||
async getData() { | ||
if (this._length < 0) { | ||
errors.throwErr(errors.ERR_INVALID_LOB); | ||
async getData(offset = 1, len = this._length) { | ||
if (!len) { | ||
len = this._length; | ||
} | ||
return await this.read(1, this._length); | ||
return await this.read(offset, len); | ||
} | ||
@@ -161,3 +161,3 @@ | ||
if (!this.conn.nscon.connected) | ||
errors.throwErr(errors.ERR_LOB_CLOSED); | ||
errors.throwErr(errors.ERR_INVALID_CONNECTION); | ||
} | ||
@@ -164,0 +164,0 @@ |
@@ -1,2 +0,2 @@ | ||
// Copyright (c) 2022, 2023, Oracle and/or its affiliates. | ||
// Copyright (c) 2022, 2024, Oracle and/or its affiliates. | ||
@@ -56,2 +56,3 @@ //----------------------------------------------------------------------------- | ||
this._poolPingInterval = params.poolPingInterval; | ||
this._poolPingTimeout = params.poolPingTimeout; | ||
this._stmtCacheSize = params.stmtCacheSize; | ||
@@ -323,2 +324,9 @@ | ||
//--------------------------------------------------------------------------- | ||
// returns the pool ping Timeout (milliseconds) | ||
//--------------------------------------------------------------------------- | ||
getPoolPingTimeout() { | ||
return this._poolPingTimeout; | ||
} | ||
//--------------------------------------------------------------------------- | ||
// returns the pool timeout | ||
@@ -368,3 +376,3 @@ //--------------------------------------------------------------------------- | ||
this._poolMin && this._freeConnectionList.length > 0) { | ||
const conn = this._freeConnectionList[this._freeConnectionList.length - 1]; | ||
const conn = this._freeConnectionList[0]; | ||
if (Date.now() - conn._lastTimeUsed < this._poolTimeout * 1000) { | ||
@@ -375,3 +383,3 @@ break; | ||
this.eventEmitter.emit('_removePoolConnection', conn); | ||
this._freeConnectionList.pop(); | ||
this._freeConnectionList.shift(); | ||
} | ||
@@ -502,7 +510,17 @@ | ||
if (requiresPing) { | ||
let pingTimer; | ||
try { | ||
if (this._poolPingTimeout) { | ||
pingTimer = setTimeout(() => { | ||
// force disconnect causes ping task to unblock | ||
// and return. | ||
conn.nscon.forceDisconnect(); | ||
}, this._poolPingTimeout); | ||
} | ||
await conn.ping(); | ||
} catch { | ||
this.eventEmitter.emit('_removePoolConnection', conn); | ||
conn.nscon.forceDisconnect(); | ||
continue; | ||
} finally { | ||
clearTimeout(pingTimer); | ||
} | ||
@@ -509,0 +527,0 @@ } |
@@ -1,2 +0,2 @@ | ||
// Copyright (c) 2022, 2023, Oracle and/or its affiliates. | ||
// Copyright (c) 2022, 2024, Oracle and/or its affiliates. | ||
@@ -107,2 +107,4 @@ //----------------------------------------------------------------------------- | ||
constants.TNS_CCAP_INBAND_NOTIFICATION; | ||
this.compileCaps[constants.TNS_CCAP_TTC5] = | ||
constants.TNS_CCAP_VECTOR_SUPPORT; | ||
} | ||
@@ -109,0 +111,0 @@ |
@@ -1,2 +0,2 @@ | ||
// Copyright (c) 2022, 2023, Oracle and/or its affiliates. | ||
// Copyright (c) 2022, 2024, Oracle and/or its affiliates. | ||
@@ -31,2 +31,3 @@ //----------------------------------------------------------------------------- | ||
const constants = require('../../constants.js'); | ||
const dataHandlerConstants = require('../../impl/datahandlers/constants.js'); | ||
@@ -202,2 +203,3 @@ module.exports = { | ||
TNS_DATA_TYPE_LFOP: 126 + 256, | ||
TNS_DATA_TYPE_VECTOR: 127, | ||
TNS_DATA_TYPE_FCRT: 127 + 256, | ||
@@ -518,39 +520,3 @@ TNS_DATA_TYPE_DNY: 128 + 256, | ||
TNS_JSON_MAX_LENGTH: 32 * 1024 * 1024, | ||
TNS_JSON_MAGIC_BYTE_1: 0xff, | ||
TNS_JSON_MAGIC_BYTE_2: 0x4a, // 'J' | ||
TNS_JSON_MAGIC_BYTE_3: 0x5a, // 'Z' | ||
TNS_JSON_VERSION: 1, | ||
TNS_JSON_FLAG_HASH_ID_UINT8: 0x0100, | ||
TNS_JSON_FLAG_HASH_ID_UINT16: 0x0200, | ||
TNS_JSON_FLAG_NUM_FNAMES_UINT16: 0x0400, | ||
TNS_JSON_FLAG_FNAMES_SEG_UINT32: 0x0800, | ||
TNS_JSON_FLAG_TINY_NODES_STAT: 0x2000, | ||
TNS_JSON_FLAG_TREE_SEG_UINT32: 0x1000, | ||
TNS_JSON_FLAG_REL_OFFSET_MODE: 0x01, | ||
TNS_JSON_FLAG_INLINE_LEAF: 0x02, | ||
TNS_JSON_FLAG_LEN_IN_PCODE: 0x04, | ||
TNS_JSON_FLAG_NUM_FNAMES_UINT32: 0x08, | ||
TNS_JSON_FLAG_IS_SCALAR: 0x10, | ||
// JSON data types | ||
TNS_JSON_TYPE_NULL: 0x30, | ||
TNS_JSON_TYPE_TRUE: 0x31, | ||
TNS_JSON_TYPE_FALSE: 0x32, | ||
TNS_JSON_TYPE_STRING_LENGTH_UINT8: 0x33, | ||
TNS_JSON_TYPE_NUMBER_LENGTH_UINT8: 0x34, | ||
TNS_JSON_TYPE_BINARY_DOUBLE: 0x36, | ||
TNS_JSON_TYPE_STRING_LENGTH_UINT16: 0x37, | ||
TNS_JSON_TYPE_STRING_LENGTH_UINT32: 0x38, | ||
TNS_JSON_TYPE_TIMESTAMP: 0x39, | ||
TNS_JSON_TYPE_BINARY_LENGTH_UINT16: 0x3a, | ||
TNS_JSON_TYPE_BINARY_LENGTH_UINT32: 0x3b, | ||
TNS_JSON_TYPE_DATE: 0x3c, | ||
TNS_JSON_TYPE_INTERVAL_YM: 0x3d, | ||
TNS_JSON_TYPE_INTERVAL_DS: 0x3e, | ||
TNS_JSON_TYPE_TIMESTAMP_TZ: 0x7c, | ||
TNS_JSON_TYPE_TIMESTAMP7: 0x7d, | ||
TNS_JSON_TYPE_BINARY_FLOAT: 0x7f, | ||
TNS_JSON_TYPE_OBJECT: 0x84, | ||
TNS_JSON_TYPE_ARRAY: 0xc0, | ||
// end-to-end metrics | ||
@@ -614,3 +580,4 @@ TNS_END_TO_END_ACTION: 0x0010, | ||
TNS_CCAP_LOB2: 42, | ||
TNS_CCAP_MAX: 45, | ||
TNS_CCAP_TTC5: 44, | ||
TNS_CCAP_MAX: 51, | ||
@@ -637,3 +604,4 @@ // compile time capability values | ||
TNS_CCAP_FIELD_VERSION_23_1_EXT_6: 23, | ||
TNS_CCAP_FIELD_VERSION_MAX: 23, | ||
TNS_CCAP_FIELD_VERSION_23_4: 24, | ||
TNS_CCAP_FIELD_VERSION_MAX: 24, | ||
TNS_CCAP_O5LOGON: 8, | ||
@@ -668,2 +636,3 @@ TNS_CCAP_O5LOGON_NP: 2, | ||
TNS_CCAP_LOB2_2GB_PREFETCH: 0x04, | ||
TNS_CCAP_VECTOR_SUPPORT: 0x08, | ||
@@ -689,11 +658,9 @@ // runtime capability indices | ||
TNS_UDS_FLAGS_IS_JSON: 0x00000100, | ||
TNS_UDS_FLAGS_IS_OSON: 0x00000800, | ||
// other constants | ||
TNS_MAX_SHORT_LENGTH: 252, | ||
TNS_ESCAPE_CHAR: 253, | ||
TNS_LONG_LENGTH_INDICATOR: 254, | ||
TNS_NULL_LENGTH_INDICATOR: 255, | ||
TNS_LONG_LENGTH_INDICATOR: dataHandlerConstants.TNS_LONG_LENGTH_INDICATOR, | ||
TNS_NULL_LENGTH_INDICATOR: dataHandlerConstants.TNS_NULL_LENGTH_INDICATOR, | ||
TNS_MAX_ROWID_LENGTH: 18, | ||
TNS_DURATION_MID: 0x80000000, | ||
TNS_DURATION_OFFSET: 60, | ||
TNS_DURATION_SESSION: 10, | ||
@@ -705,10 +672,4 @@ TNS_MAX_LONG_LENGTH: 0x7fffffff, | ||
TNS_MAX_CONNECT_DATA: 230, | ||
TNS_CHUNK_SIZE: 32767, | ||
TNS_MAX_UROWID_LENGTH: 3950, | ||
TNS_HAS_REGION_ID: 0x80, | ||
// timezone offsets | ||
TZ_HOUR_OFFSET: 20, | ||
TZ_MINUTE_OFFSET: 60, | ||
// drcp release mode | ||
@@ -753,2 +714,6 @@ DRCP_DEAUTHENTICATE: 0x00000002, | ||
TNS_OBJ_TDS_TYPE_BINARY_FLOAT: 37, | ||
TNS_OBJ_TDS_TYPE_START_EMBED_ADT: 39, | ||
TNS_OBJ_TDS_TYPE_END_EMBED_ADT: 40, | ||
TNS_OBJ_TDS_TYPE_SUBTYPE_MARKER: 43, | ||
TNS_OBJ_TDS_TYPE_EMBED_ADT_INFO: 44, | ||
TNS_OBJ_TDS_TYPE_BINARY_DOUBLE: 45, | ||
@@ -772,7 +737,10 @@ | ||
// vector constants | ||
TNS_VECTOR_MAX_LENGTH: 1048576, | ||
VECTOR_FORMAT_FLEX: 0, | ||
VECTOR_META_FLAG_FLEXIBLE_DIM: 1, | ||
// other constants | ||
PACKET_HEADER_SIZE: 8, | ||
NUMBER_AS_TEXT_CHARS: 172, | ||
NUMBER_MAX_DIGITS: 40, | ||
BUFFER_CHUNK_SIZE: 65536, | ||
CHUNKED_BYTES_CHUNK_SIZE: 65536, | ||
@@ -779,0 +747,0 @@ |
@@ -325,3 +325,3 @@ // Copyright (c) 2022, 2023, Oracle and/or its affiliates. | ||
this.conn.dbName = this.sessionData['AUTH_SC_DBUNIQUE_NAME']; | ||
this.conn.maxOpenCursors = Number(this.sessionData['AUTH_MAX_OPEN_CURSORS']); | ||
this.conn.maxOpenCursors = Number(this.sessionData['AUTH_MAX_OPEN_CURSORS'] || 0); | ||
this.conn.serviceName = this.sessionData['AUTH_SC_SERVICE_NAME']; | ||
@@ -328,0 +328,0 @@ this.conn.instanceName = this.sessionData['AUTH_INSTANCENAME']; |
@@ -1,2 +0,2 @@ | ||
// Copyright (c) 2022, 2023, Oracle and/or its affiliates. | ||
// Copyright (c) 2022, 2024, Oracle and/or its affiliates. | ||
@@ -93,7 +93,7 @@ //----------------------------------------------------------------------------- | ||
// batch error codes | ||
let numEntries = buf.readUB2(); // batch error codes array | ||
if (numEntries > 0) { | ||
const numErrors = buf.readUB2(); // batch error codes array | ||
if (numErrors > 0) { | ||
this.errorInfo.batchErrors = []; | ||
const firstByte = buf.readUInt8(); | ||
for (let i = 0; i < numEntries; i++) { | ||
for (let i = 0; i < numErrors; i++) { | ||
if (firstByte === constants.TNS_LONG_LENGTH_INDICATOR) { | ||
@@ -111,10 +111,17 @@ buf.skipUB4(); // chunk length ignored | ||
// batch error offset | ||
numEntries = buf.readUB2(); // batch error row offset array | ||
if (numEntries > 0) { | ||
const numOffsets = buf.readUB4(); // batch error row offset array | ||
if (numOffsets > 0) { | ||
if (numOffsets > 65535) { | ||
errors.throwErr(errors.ERR_TOO_MANY_BATCH_ERRORS); | ||
} | ||
const firstByte = buf.readUInt8(); | ||
for (let i = 0; i < numEntries; i++) { | ||
let offset; | ||
for (let i = 0; i < numOffsets; i++) { | ||
if (firstByte === constants.TNS_LONG_LENGTH_INDICATOR) { | ||
buf.skipUB4(); // chunk length ignored | ||
} | ||
this.errorInfo.batchErrors[i].offset = buf.readUB4(); | ||
offset = buf.readUB4(); | ||
if (i < numErrors) { | ||
this.errorInfo.batchErrors[i].offset = offset; | ||
} | ||
} | ||
@@ -127,6 +134,6 @@ if (firstByte === constants.TNS_LONG_LENGTH_INDICATOR) { | ||
// batch error messages | ||
numEntries = buf.readUB2(); // batch error messages array | ||
if (numEntries > 0) { | ||
const errMsgArr = buf.readUB2(); // batch error messages array | ||
if (errMsgArr > 0) { | ||
buf.skipBytes(1); // ignore packed size | ||
for (let i = 0; i < numEntries; i++) { | ||
for (let i = 0; i < errMsgArr; i++) { | ||
buf.skipUB2(); // skip chunk length | ||
@@ -281,3 +288,3 @@ | ||
if (this.connection._drcpEstablishSession) { | ||
this.connection.resetStatementCache(); | ||
this.connection.statementCache.clearOpenCursors(); | ||
} | ||
@@ -297,3 +304,3 @@ } | ||
} | ||
if (this.connection._cursorsToClose.size > 0 && !this.connection._drcpEstablishSession) { | ||
if (this.connection.statementCache._cursorsToClose.size > 0 && !this.connection._drcpEstablishSession) { | ||
this.writeCloseCursorsPiggyBack(buf); | ||
@@ -327,7 +334,3 @@ } | ||
buf.writeUInt8(1); | ||
buf.writeUB4(this.connection._cursorsToClose.size); | ||
for (const cursorNum of this.connection._cursorsToClose.keys()) { | ||
buf.writeUB4(cursorNum); | ||
} | ||
this.connection._cursorsToClose.clear(); | ||
this.connection.statementCache.writeCursorsToClose(buf); | ||
} | ||
@@ -334,0 +337,0 @@ |
@@ -1,2 +0,2 @@ | ||
// Copyright (c) 2022, 2023, Oracle and/or its affiliates. | ||
// Copyright (c) 2022, 2024, Oracle and/or its affiliates. | ||
@@ -395,5 +395,6 @@ //----------------------------------------------------------------------------- | ||
[constants.TNS_DATA_TYPE_OER, constants.TNS_DATA_TYPE_OER, constants.TNS_TYPE_REP_UNIVERSAL], | ||
[constants.TNS_DATA_TYPE_OAC, constants.TNS_DATA_TYPE_OAC, constants.TNS_TYPE_REP_UNIVERSAL] | ||
[constants.TNS_DATA_TYPE_OAC, constants.TNS_DATA_TYPE_OAC, constants.TNS_TYPE_REP_UNIVERSAL], | ||
[constants.TNS_DATA_TYPE_VECTOR, constants.TNS_DATA_TYPE_VECTOR, constants.TNS_TYPE_REP_UNIVERSAL] | ||
]; | ||
module.exports = DataTypeMessage; |
@@ -1,2 +0,2 @@ | ||
// Copyright (c) 2022, 2023, Oracle and/or its affiliates. | ||
// Copyright (c) 2022, 2024, Oracle and/or its affiliates. | ||
@@ -120,3 +120,3 @@ //----------------------------------------------------------------------------- | ||
} else if (this.errorInfo.num !== 0 && this.errorInfo.cursorId !== 0) { | ||
this.connection.statementCache.delete(this.statement.sql); | ||
this.connection.statementCache._cachedStatements.delete(this.statement.sql); | ||
this.statement.returnToCache = false; | ||
@@ -152,2 +152,4 @@ } | ||
resultSet.metadata = []; | ||
const metadata = []; | ||
const queryVars = []; | ||
for (let i = 0; i < statement.numQueryVars; i++) { | ||
@@ -158,6 +160,5 @@ const variable = this.processColumnInfo(buf, i + 1); | ||
} | ||
statement.queryVars.push(variable); | ||
resultSet.metadata.push(variable.fetchInfo); | ||
queryVars.push(variable); | ||
metadata.push(variable.fetchInfo); | ||
} | ||
let numBytes = buf.readUB4(); | ||
@@ -176,2 +177,9 @@ if (numBytes > 0) { | ||
/* | ||
* The message state(resultSet) and statement state(queryVars) is modified | ||
* at end of the DescribeInfo function so that an OutOfPacketsError | ||
* won't cause partial information state to be stored. | ||
*/ | ||
resultSet.metadata = metadata; | ||
statement.queryVars = queryVars; | ||
this.resultSetsToSetup.push(resultSet); | ||
@@ -230,2 +238,3 @@ } | ||
fetchInfo.isJson = Boolean(udsFlags & constants.TNS_UDS_FLAGS_IS_JSON); | ||
fetchInfo.isOson = Boolean(udsFlags & constants.TNS_UDS_FLAGS_IS_OSON); | ||
if (buf.caps.ttcFieldVersion >= constants.TNS_CCAP_FIELD_VERSION_23_1) { | ||
@@ -262,2 +271,15 @@ numBytes = buf.readUB4(); | ||
} | ||
if (buf.caps.ttcFieldVersion >= constants.TNS_CCAP_FIELD_VERSION_23_4) { | ||
const dimensions = buf.readUB4(); | ||
const vectorFormat = buf.readUInt8(); | ||
const vectorFlags = buf.readUInt8(); | ||
if (fetchInfo.dbType === types.DB_TYPE_VECTOR) { | ||
if (!(vectorFlags & constants.VECTOR_META_FLAG_FLEXIBLE_DIM)) { | ||
fetchInfo.vectorDimensions = dimensions; | ||
} | ||
if (vectorFormat !== constants.VECTOR_FORMAT_FLEX) { | ||
fetchInfo.vectorFormat = vectorFormat; | ||
} | ||
} | ||
} | ||
@@ -490,2 +512,4 @@ switch (fetchInfo.dbType) { | ||
colValue = buf.readOson(); | ||
} else if (oraTypeNum === constants.TNS_DATA_TYPE_VECTOR) { | ||
colValue = buf.readVector(); | ||
} else if (oraTypeNum === constants.TNS_DATA_TYPE_INT_NAMED) { | ||
@@ -599,3 +623,4 @@ const obj = buf.readDbObject(); | ||
variable.type === types.DB_TYPE_BLOB || | ||
variable.type === types.DB_TYPE_JSON) { | ||
variable.type === types.DB_TYPE_JSON || | ||
variable.type === types.DB_TYPE_VECTOR) { | ||
if (variable.type !== variable.fetchInfo.fetchType) { | ||
@@ -685,2 +710,5 @@ variable.type = variable.fetchInfo.fetchType; | ||
maxSize = lobPrefetchLength = constants.TNS_JSON_MAX_LENGTH; | ||
} else if (variable.type === types.DB_TYPE_VECTOR) { | ||
contFlag = constants.TNS_LOB_PREFETCH_FLAG; | ||
maxSize = lobPrefetchLength = constants.TNS_VECTOR_MAX_LENGTH; | ||
} | ||
@@ -806,4 +834,6 @@ buf.writeUInt8(oraTypeNum); | ||
} else if (oraTypeNum === constants.TNS_DATA_TYPE_BINARY_DOUBLE) { | ||
buf.writeUInt8(8); | ||
buf.writeBinaryDouble(value); | ||
} else if (oraTypeNum === constants.TNS_DATA_TYPE_BINARY_FLOAT) { | ||
buf.writeUInt8(4); | ||
buf.writeBinaryFloat(value); | ||
@@ -836,2 +866,4 @@ } else if (oraTypeNum === constants.TNS_DATA_TYPE_CURSOR) { | ||
buf.writeOson(value); | ||
} else if (oraTypeNum === constants.TNS_DATA_TYPE_VECTOR) { | ||
buf.writeVector(value); | ||
} else if (oraTypeNum === constants.TNS_DATA_TYPE_INT_NAMED) { | ||
@@ -838,0 +870,0 @@ buf.writeDbObject(value); |
@@ -1,2 +0,2 @@ | ||
// Copyright (c) 2022, 2023, Oracle and/or its affiliates. | ||
// Copyright (c) 2022, 2024, Oracle and/or its affiliates. | ||
@@ -29,7 +29,8 @@ //----------------------------------------------------------------------------- | ||
const { BaseBuffer } = require('./buffer.js'); | ||
const { BaseBuffer } = require('../../impl/datahandlers/buffer.js'); | ||
const { Buffer } = require('buffer'); | ||
const constants = require("./constants.js"); | ||
const oson = require('./oson.js'); | ||
const constants = require('./constants.js'); | ||
const oson = require('../../impl/datahandlers/oson.js'); | ||
const utils = require('./utils.js'); | ||
const vector = require('../../impl/datahandlers/vector.js'); | ||
const errors = require("../../errors.js"); | ||
@@ -399,2 +400,18 @@ | ||
/** | ||
* Reads VECTOR data (QLocator followed by data) and decodes it into a | ||
* JavaScript object. | ||
*/ | ||
readVector() { | ||
const numBytes = this.readUB4(); | ||
if (numBytes === 0) { | ||
return null; | ||
} | ||
this.skipUB8(); // size (unused) | ||
this.skipUB4(); // chunk size (unused) | ||
const decoder = new vector.VectorDecoder(this.readBytesWithLength()); | ||
this.skipBytesChunked(); // locator (unused) | ||
return decoder.decode(); | ||
} | ||
skipBytesChunked() { | ||
@@ -484,2 +501,5 @@ const numBytes = this.readUInt8(); | ||
} | ||
if (!this.nsi.ntAdapter) { | ||
errors.throwErr(errors.ERR_INVALID_CONNECTION); | ||
} | ||
this.nsi.ntAdapter.send(buf); | ||
@@ -543,2 +563,36 @@ } | ||
/** | ||
* Encodes a JavaScript object into VECTOR data and then writes it (QLocator | ||
* followed by data) to the buffer. | ||
*/ | ||
writeVector(value) { | ||
const encoder = new vector.VectorEncoder(); | ||
const buf = encoder.encode(value); | ||
this.writeQLocator(buf.length); | ||
this.writeBytesWithLength(buf); | ||
} | ||
//--------------------------------------------------------------------------- | ||
// writeQLocator() | ||
// | ||
// Writes a QLocator. QLocators are always 40 bytes in length. | ||
//--------------------------------------------------------------------------- | ||
writeQLocator(numBytes) { | ||
this.writeUB4(40); // QLocator length | ||
this.writeUInt8(40); // repeated length | ||
this.writeUInt16BE(38); // internal length | ||
this.writeUInt16BE(constants.TNS_LOB_QLOCATOR_VERSION); | ||
this.writeUInt8(constants.TNS_LOB_LOC_FLAGS_VALUE_BASED | | ||
constants.TNS_LOB_LOC_FLAGS_BLOB | constants.TNS_LOB_LOC_FLAGS_ABSTRACT); | ||
this.writeUInt8(constants.TNS_LOB_LOC_FLAGS_INIT); | ||
this.writeUInt16BE(0); // additional flags | ||
this.writeUInt16BE(1); // byt1 | ||
this.writeUInt64BE(numBytes); | ||
this.writeUInt16BE(0); // unused | ||
this.writeUInt16BE(0); // csid | ||
this.writeUInt16BE(0); // unused | ||
this.writeUInt64BE(0); // unused | ||
this.writeUInt64BE(0); // unused | ||
} | ||
} | ||
@@ -545,0 +599,0 @@ |
@@ -1,2 +0,2 @@ | ||
// Copyright (c) 2022, 2023, Oracle and/or its affiliates. | ||
// Copyright (c) 2022, 2024, Oracle and/or its affiliates. | ||
@@ -534,2 +534,14 @@ //----------------------------------------------------------------------------- | ||
/** | ||
* Force Disconnect the stream, primarily used | ||
* to disconnect dead/hung connections. | ||
*/ | ||
forceDisconnect(err) { | ||
if (!this.connected) { | ||
return; | ||
} | ||
this.ntAdapter.stream.destroy(err); | ||
this.connected = false; | ||
} | ||
/** | ||
* Disconnect | ||
@@ -536,0 +548,0 @@ * @param {int} type of disconnect |
@@ -1,2 +0,2 @@ | ||
// Copyright (c) 2022, 2023, Oracle and/or its affiliates. | ||
// Copyright (c) 2022, 2024, Oracle and/or its affiliates. | ||
@@ -222,6 +222,6 @@ //----------------------------------------------------------------------------- | ||
* Single line comments consist of two dashes and all characters up to the | ||
* next line break. This method is called when the first dash is detected | ||
* and checks for the subsequent dash. If found, the single line comment | ||
* is traversed and the current position is updated; otherwise, the | ||
* current position is left untouched. | ||
* next line break (or the end of the data). This method is called when | ||
* the first dash is detected and checks for the subsequent dash. If found, | ||
* the single line comment is traversed and the current position is updated; | ||
* otherwise, the current position is left untouched. | ||
*/ | ||
@@ -237,7 +237,6 @@ _parseSingleLineComment() { | ||
if (ch !== '-') { | ||
break; | ||
return; | ||
} | ||
inComment = true; | ||
} else if (ch === '\n') { | ||
this.pos = pos; | ||
break; | ||
@@ -247,2 +246,3 @@ } | ||
} | ||
this.pos = pos; | ||
} | ||
@@ -249,0 +249,0 @@ |
@@ -1,2 +0,2 @@ | ||
// Copyright (c) 2023, Oracle and/or its affiliates. | ||
// Copyright (c) 2023, 2024, Oracle and/or its affiliates. | ||
@@ -37,2 +37,3 @@ //----------------------------------------------------------------------------- | ||
const types = require('./types.js'); | ||
const nodbUtil = require('./util.js'); | ||
@@ -90,5 +91,5 @@ //----------------------------------------------------------------------------- | ||
if (value === undefined || value === null || | ||
typeof value === 'number' || typeof value === 'string' || | ||
typeof value === 'boolean' || Buffer.isBuffer(value) || | ||
util.isDate(value)) | ||
typeof value === 'number' || typeof value === 'string' || | ||
typeof value === 'boolean' || Buffer.isBuffer(value) || | ||
util.isDate(value) || nodbUtil.isVectorValue(value)) | ||
return value; | ||
@@ -225,2 +226,10 @@ | ||
// handle vectors | ||
} else if (value instanceof Float32Array || value instanceof Float64Array || | ||
value instanceof Int8Array) { | ||
checkType(info, options, types.DB_TYPE_VECTOR); | ||
return value; | ||
} else if (info.type === types.DB_TYPE_VECTOR && Array.isArray(value)) { | ||
return new Float64Array(value); | ||
// handle arrays | ||
@@ -227,0 +236,0 @@ } else if (options.allowArray && Array.isArray(value)) { |
@@ -1,2 +0,2 @@ | ||
// Copyright (c) 2022, 2023, Oracle and/or its affiliates. | ||
// Copyright (c) 2022, 2024, Oracle and/or its affiliates. | ||
@@ -202,2 +202,5 @@ //----------------------------------------------------------------------------- | ||
{ oraTypeNum: 109, csfrm: constants.CSFRM_IMPLICIT, bufferSizeFactor: 2147483647 }); | ||
const DB_TYPE_VECTOR = new DbType(2033, | ||
"DB_TYPE_VECTOR", "VECTOR", | ||
{ oraTypeNum: 127 }); | ||
@@ -280,2 +283,7 @@ // database type conversion map: the top level key refers to the database | ||
])], | ||
[DB_TYPE_VECTOR, new Map([ | ||
[DB_TYPE_VARCHAR, DB_TYPE_LONG], | ||
[DB_TYPE_LONG, DB_TYPE_LONG], | ||
[DB_TYPE_CLOB, DB_TYPE_CLOB] | ||
])], | ||
]); | ||
@@ -313,3 +321,4 @@ | ||
[DB_TYPE_VARCHAR, DB_TYPE_VARCHAR], | ||
[DB_TYPE_XMLTYPE, DB_TYPE_XMLTYPE] | ||
[DB_TYPE_XMLTYPE, DB_TYPE_XMLTYPE], | ||
[DB_TYPE_VECTOR, DB_TYPE_VECTOR] | ||
]); | ||
@@ -359,2 +368,3 @@ | ||
DB_TYPE_VARCHAR, | ||
DB_TYPE_VECTOR, | ||
DB_TYPE_CONVERSION_MAP, | ||
@@ -361,0 +371,0 @@ DB_TYPE_FETCH_TYPE_MAP, |
@@ -330,2 +330,29 @@ // Copyright (c) 2016, 2023, Oracle and/or its affiliates. | ||
//----------------------------------------------------------------------------- | ||
// isVectorValue() | ||
// | ||
// Returns true for list of typed arrays supported for vector column types | ||
// | ||
// ----------------------------------------------------------------------------- | ||
function isVectorValue(value) { | ||
return (value instanceof Float32Array || | ||
value instanceof Float64Array || | ||
value instanceof Int8Array); | ||
} | ||
//----------------------------------------------------------------------------- | ||
// makeDate() | ||
// | ||
// Returns a date from the given components. | ||
// | ||
// ----------------------------------------------------------------------------- | ||
function makeDate(useLocal, year, month, day, hour, minute, | ||
second, fseconds, offset) { | ||
if (useLocal) { | ||
return new Date(year, month - 1, day, hour, minute, second, fseconds); | ||
} | ||
return new Date(Date.UTC(year, month - 1, day, hour, minute, second, | ||
fseconds) - offset * 60000); | ||
} | ||
// define exports | ||
@@ -350,3 +377,5 @@ module.exports = { | ||
isTokenValid, | ||
isVectorValue, | ||
isXid, | ||
makeDate, | ||
preventConcurrent, | ||
@@ -353,0 +382,0 @@ serialize, |
@@ -1,2 +0,2 @@ | ||
// Copyright (c) 2023, Oracle and/or its affiliates. | ||
// Copyright (c) 2023, 2024, Oracle and/or its affiliates. | ||
@@ -33,5 +33,5 @@ //----------------------------------------------------------------------------- | ||
VERSION_MAJOR: 6, | ||
VERSION_MINOR: 3, | ||
VERSION_MINOR: 4, | ||
VERSION_PATCH: 0, | ||
VERSION_SUFFIX: '' | ||
}; |
@@ -1,2 +0,2 @@ | ||
Copyright (c) 2015, 2023 Oracle and/or its affiliates. | ||
Copyright (c) 2015, 2024 Oracle and/or its affiliates. | ||
@@ -3,0 +3,0 @@ This software is dual-licensed to you under the Universal Permissive License |
@@ -1,1 +0,1 @@ | ||
Copyright (c) 2015, 2023, Oracle and/or its affiliates. | ||
Copyright (c) 2015, 2024, Oracle and/or its affiliates. |
{ | ||
"name": "oracledb", | ||
"version": "6.3.0", | ||
"version": "6.4.0", | ||
"description": "A Node.js module for Oracle Database access from JavaScript and TypeScript", | ||
@@ -5,0 +5,0 @@ "license": "(Apache-2.0 OR UPL-1.0)", |
@@ -1,2 +0,2 @@ | ||
# node-oracledb version 6.3.0 | ||
# node-oracledb version 6.4.0 | ||
@@ -7,3 +7,3 @@ The node-oracledb add-on for Node.js powers high performance Oracle Database | ||
Use node-oracledb 6.3.0 to connect Node.js 14.6, or later, to Oracle | ||
Use node-oracledb 6.4.0 to connect Node.js 14.6, or later, to Oracle | ||
Database. Older versions of node-oracledb may work with older versions of | ||
@@ -52,3 +52,3 @@ Node.js. | ||
Copyright (c) 2015, 2023, Oracle and/or its affiliates. | ||
Copyright (c) 2015, 2024, Oracle and/or its affiliates. | ||
@@ -55,0 +55,0 @@ This software is dual-licensed to you under the Universal Permissive License |
107
24807
3360403