Skip to content

Commit e4a261d

Browse files
committed
Add support for binary vector (Oracle Database 23ai feature) and eslint fixes in code
1 parent 0d72c1b commit e4a261d

File tree

17 files changed

+95
-24
lines changed

17 files changed

+95
-24
lines changed

examples/vectortype1.js

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -93,33 +93,42 @@ async function run() {
9393
VCOL8 VECTOR(4, int8),
9494
VCOL VECTOR(4),
9595
VCOLFlexDouble VECTOR(*, *),
96-
VCOLFlexFloat VECTOR(*, *))`);
96+
VCOLFlexFloat VECTOR(*, *),
97+
VCOLBinary VECTOR(16, binary))`);
9798

9899
const arr = [2345.67, 12.2, -23.4, -65.2];
99100
const float64arr = new Float64Array(arr);
100101
const float32arr = new Float32Array(arr);
101102
const int8arr = new Int8Array([126, 125, -126, -23]);
103+
104+
// 16 dimensions numbering from left/msb
105+
// 1,1,1,1,0,0,0,0
106+
// 1,1,0,0,1,0,0,0
107+
const uInt8Arr = new Uint8Array([240, 200]);
108+
102109
// Add both float32 and float64 range elements
103110
const arrFlexDouble = [2345.67, 12.666428727762776];
104111
// Add only float32 range elements
105112
const arrFlexFloat32 = [2345.67, 12.66, 43.23];
106113

107114
console.log('Inserting Vector ');
108115
result = await connection.execute(`insert into ${tableName} values(:id, :vec32, :vec64, :vec8, :vec,
109-
:vecFlexDouble, :vecFlexFloat)`,
116+
:vecFlexDouble, :vecFlexFloat, :vecBinary)`,
110117
{ id: 1,
111118
vec32: float32arr,
112119
vec64: float64arr,
113120
vec8: int8arr,
114121
vec: {type: oracledb.DB_TYPE_VECTOR, val: arr},
115122
vecFlexDouble: {type: oracledb.DB_TYPE_VECTOR, val: arrFlexDouble},
116-
vecFlexFloat: {type: oracledb.DB_TYPE_VECTOR, val: arrFlexFloat32}
123+
vecFlexFloat: {type: oracledb.DB_TYPE_VECTOR, val: arrFlexFloat32},
124+
vecBinary: {type: oracledb.DB_TYPE_VECTOR, val: uInt8Arr}
117125
});
118126
console.log('Rows inserted: ' + result.rowsAffected);
119127

120128
console.log('Query Results:');
121129
result = await connection.execute(
122-
`select id, VCOL32, VCOL64, VCOL8, VCOL, VCOLFlexDouble, VCOLFlexFloat from ${tableName} ORDER BY id`);
130+
`select id, VCOL32, VCOL64, VCOL8, VCOL, VCOLFlexDouble, VCOLFlexFloat, VCOLBinary
131+
from ${tableName} ORDER BY id`);
123132
console.log("Query metadata:", result.metaData);
124133
console.log("Query rows:", result.rows);
125134
const vec32 = result.rows[0].VCOL32;
@@ -128,13 +137,15 @@ async function run() {
128137
const vec = result.rows[0].VCOL;
129138
const vecFlexDouble = result.rows[0].VCOLFLEXDOUBLE;
130139
const vecFlexFloat = result.rows[0].VCOLFLEXFLOAT;
140+
const vecBinary = result.rows[0].VCOLBINARY;
131141

132142
assert(vec32.constructor, Array);
133143
assert(vec64.constructor, Array);
134144
assert(vec.constructor, Array);
135145
assert(vecFlexDouble.constructor, Array);
136146
assert(vecFlexFloat.constructor, Array);
137147
assert(vec8.constructor, Array);
148+
assert(vecBinary.constructor, Array);
138149

139150
// Reading vector as string.
140151
console.log("Fetch Vector Column as string");

lib/configProviders/azure.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,4 +165,3 @@ class AzureProvider extends base {
165165
}
166166
}
167167
module.exports = AzureProvider;
168-

lib/configProviders/base.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,5 +97,3 @@ class base {
9797

9898
}
9999
module.exports = {base};
100-
101-

lib/configProviders/ociobject.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,4 +201,3 @@ class OCIProvider extends base {
201201
}
202202
}
203203
module.exports = OCIProvider;
204-

lib/connection.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -202,9 +202,7 @@ class Connection extends EventEmitter {
202202
typeof value === 'boolean' ||
203203
typeof value === 'bigint' ||
204204
Array.isArray(value) ||
205-
value instanceof Float32Array ||
206-
value instanceof Float64Array ||
207-
value instanceof Int8Array ||
205+
nodbUtil.isVectorValue(value) ||
208206
Buffer.isBuffer(value) ||
209207
util.types.isDate(value) ||
210208
value instanceof Lob ||

lib/constants.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,5 +205,6 @@ module.exports = {
205205
VECTOR_FORMAT_FLOAT32: 2,
206206
VECTOR_FORMAT_FLOAT64: 3,
207207
VECTOR_FORMAT_INT8: 4,
208+
VECTOR_FORMAT_BINARY: 5,
208209

209210
};

lib/impl/datahandlers/constants.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ module.exports = {
3232

3333
// vector constants
3434
TNS_VECTOR_MAGIC_BYTE: 0xDB,
35-
TNS_VECTOR_VERSION: 0,
35+
TNS_VECTOR_VERSION_BASE: 0,
36+
TNS_VECTOR_VERSION_WITH_BINARY: 1,
3637

3738
// vector flags
3839
TNS_VECTOR_FLAG_NORMSRC: 0x0010,
@@ -99,6 +100,7 @@ module.exports = {
99100
VECTOR_FORMAT_FLOAT32: constants.VECTOR_FORMAT_FLOAT32,
100101
VECTOR_FORMAT_FLOAT64: constants.VECTOR_FORMAT_FLOAT64,
101102
VECTOR_FORMAT_INT8: constants.VECTOR_FORMAT_INT8,
103+
VECTOR_FORMAT_BINARY: constants.VECTOR_FORMAT_BINARY,
102104

103105
TNS_NULL_LENGTH_INDICATOR: 255,
104106
TNS_LONG_LENGTH_INDICATOR: 254,

lib/impl/datahandlers/vector.js

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,11 @@ class VectorDecoder extends BaseBuffer {
5050
errors.throwErr(errors.ERR_UNEXPECTED_DATA,
5151
Buffer.from([magicByte]).toString('hex'));
5252
const version = this.readUInt8();
53-
if (version != constants.TNS_VECTOR_VERSION)
53+
if (version > constants.TNS_VECTOR_VERSION_WITH_BINARY)
5454
errors.throwErr(errors.ERR_VECTOR_VERSION_NOT_SUPPORTED, version);
5555
const flags = this.readUInt16BE();
5656
const vectorFormat = this.readUInt8();
57-
const numElements = this.readUInt32BE();
57+
let numElements = this.readUInt32BE();
5858
let elementSize, result;
5959
if (vectorFormat === constants.VECTOR_FORMAT_FLOAT32) {
6060
elementSize = 4;
@@ -65,6 +65,11 @@ class VectorDecoder extends BaseBuffer {
6565
} else if (vectorFormat === constants.VECTOR_FORMAT_INT8) {
6666
elementSize = 1;
6767
result = new Int8Array(numElements);
68+
} else if (vectorFormat === constants.VECTOR_FORMAT_BINARY) {
69+
elementSize = 1;
70+
// The number of dimensions are assumed to be multiple of 8.
71+
numElements = numElements / 8;
72+
result = new Uint8Array(numElements);
6873
} else {
6974
errors.throwErr(errors.ERR_VECTOR_FORMAT_NOT_SUPPORTED, vectorFormat);
7075
}
@@ -100,13 +105,21 @@ class VectorEncoder extends GrowableBuffer {
100105
// determine some basic information about the vector
101106
let vectorFormat = constants.VECTOR_FORMAT_FLOAT32;
102107
let writeFn = this.writeBinaryFloat.bind(this);
108+
let numElements = value.length;
109+
let vectorVersion = constants.TNS_VECTOR_VERSION_BASE;
103110

104111
if (Array.isArray(value) || value instanceof Float64Array) {
105112
vectorFormat = constants.VECTOR_FORMAT_FLOAT64;
106113
writeFn = this.writeBinaryDouble.bind(this);
107114
} else if (value instanceof Int8Array) {
108115
vectorFormat = constants.VECTOR_FORMAT_INT8;
109116
writeFn = this.writeSB1.bind(this);
117+
} else if (value.constructor.name === 'Uint8Array') {
118+
vectorFormat = constants.VECTOR_FORMAT_BINARY;
119+
// The number of dimensions are assumed to be multiple of 8.
120+
numElements = numElements * 8;
121+
vectorVersion = constants.TNS_VECTOR_VERSION_WITH_BINARY;
122+
writeFn = this.writeUInt8.bind(this);
110123
}
111124

112125
// Let server generate the norm (TNS_VECTOR_FLAG_NORMSRC)
@@ -115,10 +128,10 @@ class VectorEncoder extends GrowableBuffer {
115128

116129
// write header
117130
this.writeUInt8(constants.TNS_VECTOR_MAGIC_BYTE);
118-
this.writeUInt8(constants.TNS_VECTOR_VERSION);
131+
this.writeUInt8(vectorVersion);
119132
this.writeUInt16BE(flags);
120133
this.writeUInt8(vectorFormat);
121-
this.writeUInt32BE(value.length);
134+
this.writeUInt32BE(numElements);
122135
this.reserveBytes(8);
123136

124137
// write data

lib/thin/protocol/capabilities.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,8 @@ class Capabilities {
118118
constants.TNS_CCAP_CTB_IMPLICIT_POOL;
119119
this.compileCaps[constants.TNS_CCAP_TTC5] =
120120
constants.TNS_CCAP_VECTOR_SUPPORT;
121+
this.compileCaps[constants.TNS_CCAP_VECTOR_FEATURES] =
122+
constants.TNS_CCAP_VECTOR_FEATURE_BINARY;
121123
}
122124

123125
initRuntimeCaps() {

lib/thin/protocol/constants.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -580,7 +580,8 @@ module.exports = {
580580
TNS_CCAP_TTC4: 40,
581581
TNS_CCAP_LOB2: 42,
582582
TNS_CCAP_TTC5: 44,
583-
TNS_CCAP_MAX: 51,
583+
TNS_CCAP_VECTOR_FEATURES: 52,
584+
TNS_CCAP_MAX: 53,
584585

585586
// compile time capability values
586587
TNS_CCAP_SQL_VERSION_MAX: 6,
@@ -636,6 +637,7 @@ module.exports = {
636637
TNS_CCAP_LOB2_2GB_PREFETCH: 0x04,
637638
TNS_CCAP_CTB_IMPLICIT_POOL: 0x08,
638639
TNS_CCAP_VECTOR_SUPPORT: 0x08,
640+
TNS_CCAP_VECTOR_FEATURE_BINARY: 0x01,
639641

640642
// runtime capability indices
641643
TNS_RCAP_COMPAT: 0,

0 commit comments

Comments
 (0)