Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
6d8768c
initial commit : added changes from v6 vector support MR
prajalg Mar 20, 2026
6c40f33
added VECTOR export in ESM entry point
prajalg Mar 20, 2026
e9d79e9
added more tests and tight check for vector literal srting for arg of…
prajalg Mar 23, 2026
37c88b7
lint fix
prajalg Mar 23, 2026
95268b9
Merge branch 'main' into vector_support_v7
prajalg Mar 23, 2026
92a3f05
added more tests including related to vector index
prajalg Mar 23, 2026
e97ade4
fix sql for oracle in show-indexes-query.test.ts
prajalg Mar 23, 2026
9716ccf
modified framework to also allow other dialects to implement the same
prajalg Mar 26, 2026
498bfc2
also added some dialects sample implementation + minor core changes
prajalg Mar 30, 2026
fa443e4
corrected snowflake sample implementation and unit tests
prajalg Mar 31, 2026
4ef6f3b
removed sample pg implementation for vector
prajalg Mar 31, 2026
362fbc0
added vector integration test for snowflake
prajalg Apr 2, 2026
81c828a
added postgres vector sample support
prajalg Apr 2, 2026
ea99dd6
added console.log for vector extension creation error
prajalg Apr 2, 2026
f8bb8e0
removed pg vector integration tests
prajalg Apr 6, 2026
cc852f6
addressed review comments
prajalg Apr 7, 2026
a1b6ccc
lint fix
prajalg Apr 7, 2026
7a61a37
made subfunctions within addIndexQuery
prajalg Apr 7, 2026
db072b7
added vector insert/update sql generation unit tests
prajalg Apr 7, 2026
cb2570a
added more tests
prajalg Apr 13, 2026
24682ce
fix:prettier
prajalg Apr 13, 2026
2b68210
removed isNumericTypedArray function and added test for binds in vect…
prajalg Apr 14, 2026
fae0d52
Merge branch 'main' into vector_support_v7
prajalg Apr 14, 2026
e1625c7
expanded acronyms + lint fix
prajalg Apr 16, 2026
3f0d687
restructured + added more tests
prajalg Apr 17, 2026
7c14284
- explicitly make abstractbase so that oracle can add its own vector
sudarshan12s May 20, 2026
a95f900
- minor change in test
sudarshan12s May 20, 2026
ae828d6
reject unsupported VECTOR index options like unique, where, include, …
sudarshan12s May 20, 2026
2bef55f
lint fix
prajalg May 20, 2026
ec5ba74
minor test fix
prajalg May 20, 2026
ee40489
add stricter check for using (only allow "hnsw" or "ivf") and order (…
prajalg May 20, 2026
292b348
removed custom isShowIndexesQuery() for oracle
prajalg May 20, 2026
f8a701b
minor cleanups
prajalg May 20, 2026
3e8552a
Merge branch 'main' into vector_support_v7
prajalg May 20, 2026
407de39
- correct reading index subtype
sudarshan12s May 21, 2026
0ad7eb9
Merge branch 'vector_support_v7' of orahub.oci.oraclecorp.com:databas…
sudarshan12s May 21, 2026
27fbf19
- fix unit test for index sql change
sudarshan12s May 21, 2026
b05b9f2
- remove unused code
sudarshan12s May 21, 2026
e2939f0
- correct some index sql generations
sudarshan12s May 21, 2026
00ccd15
- add more tests
sudarshan12s May 21, 2026
e06bb13
- remove oracle specifc index options in common layer
sudarshan12s May 21, 2026
3831c67
- add more tests
sudarshan12s May 21, 2026
52894fe
lint fix
prajalg May 21, 2026
ef8751e
added db version check for oracle INDEX_SUBTYPE column
prajalg May 21, 2026
9efae86
removed early actual connection acquisition in showIndex()
prajalg May 21, 2026
ba2f300
removed NULL literal and generated sql dynamically
prajalg May 21, 2026
46139c8
corrected INDEX_SUBTYPE compatibility unit test
prajalg May 21, 2026
00e77e1
removed pg and snowflake changes
prajalg May 22, 2026
484a3d9
added some comments
prajalg May 22, 2026
550ebf2
address bot comments
prajalg May 28, 2026
9f1579e
updated test expectations for vector
prajalg May 29, 2026
f42eebe
some minor changes + addressed bot comments
prajalg May 29, 2026
c770094
meta: update dependency esbuild to v0.28.1 [security] (#18237)
renovate[bot] Jun 13, 2026
3fce97b
Merge branch 'main' into vector_support_v7
prajalg Jun 30, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@
"chai": "4.5.0",
"concurrently": "9.2.1",
"cross-env": "10.1.0",
"esbuild": "0.28.0",
"esbuild": "0.28.1",
"eslint": "8.57.1",
"eslint-plugin-jsdoc": "61.7.1",
"eslint-plugin-mocha": "10.5.0",
Expand Down
211 changes: 211 additions & 0 deletions packages/core/src/abstract-dialect/data-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2855,6 +2855,217 @@ export class TSVECTOR extends AbstractDataType<string> {
}
}

export interface VectorOptions {
/**
* Optional vector dimension.
*/
dimension?: number;
/**
* Optional dialect-specific element format (for example float32, int8, binary).
*/
format?: string;
}

/**
* Numeric typed arrays accepted as vector values.
*/
export type NumericTypedArray =
| Int8Array
| Uint8Array
| Uint8ClampedArray
| Int16Array
| Uint16Array
| Int32Array
| Uint32Array
| Float32Array
| Float64Array;

// Dialects may accept plain arrays or any number-backed typed array. The generic validator
// checks only the container shape; dialects are responsible for validating dimensions and values.
export type VectorValue = number[] | NumericTypedArray;

/**
* The VECTOR type stores ordered numeric vectors.
*
* Availability depends on the dialect (for example Oracle, Snowflake, pgvector, ...); check your dialect’s
* documentation to confirm supported element formats and dimensions.
*
* __Fallback policy:__
* If this type is not supported, an error will be raised.
*
* This shared base exists for dialect-specific VECTOR implementations. Dialects that can use Sequelize's
* generic {@link VectorOptions} may extend {@link VECTOR}; dialects with a different option shape may extend
* this class directly with their own options type.
*
* @example
* ```ts
* DataTypes.VECTOR
* DataTypes.VECTOR(1536)
* DataTypes.VECTOR(1536, 'float32')
* DataTypes.VECTOR({ dimension: 1024, format: 'int8' })
* DataTypes.VECTOR({ dimension: 2048 })
* ```
*
* @category DataTypes
*/
export abstract class AbstractVECTORBase<
TOptions extends object,
> extends AbstractDataType<VectorValue> {
readonly options!: TOptions;

validate(value: unknown): asserts value is VectorValue {
if (this._getVectorIterable(value)) {
return;
}

ValidationErrorItem.throwDataTypeValidationError(
util.format('%O is not a valid vector', value),
);
}

protected _getVectorIterable(value: unknown): VectorValue | null {
if (Array.isArray(value) || isTypedArrayIterable(value)) {
return value;
}

return null;
}

protected _validateVectorElement(item: unknown): number {
if (typeof item !== 'number' || !Number.isFinite(item)) {
ValidationErrorItem.throwDataTypeValidationError(
util.format('%O is not a valid vector', item),
);
}

return item;
}

protected _validateDimension(dimension: number, max?: number): number {
if (!Number.isInteger(dimension) || dimension <= 0) {
throw new TypeError(`Invalid VECTOR dimension: ${dimension}`);
}

if (max !== undefined && dimension > max) {
throw new TypeError(`Invalid VECTOR dimension: ${dimension} (max ${max})`);
}

return dimension;
}

protected _checkOptionSupport(dialect: AbstractDialect) {
if (!dialect.supports.dataTypes.VECTOR) {
throwUnsupportedDataType(dialect, 'VECTOR');
}
}

protected abstract _getTypeName(): string;

protected _getSqlOptionParts(): string[] {
return [];
}

toSql(): string {
const parts = this._getSqlOptionParts();

return parts.length ? `${this._getTypeName()}(${parts.join(', ')})` : this._getTypeName();
}
}

/**
* Generic VECTOR implementation used by dialects whose options fit {@link VectorOptions}.
* Dialects with stricter option models can extend {@link AbstractVECTORBase} directly.
*/
export class VECTOR extends AbstractVECTORBase<VectorOptions> {
/** @hidden */
static readonly [DataTypeIdentifier]: string = 'VECTOR';

readonly options: VectorOptions;

constructor();
constructor(dimension: number, format?: string);
constructor(options: VectorOptions);
/** @hidden */
constructor(
...args:
| []
| [dimension: number]
| [dimension: number, format: string]
| [options: VectorOptions]
);
constructor(dimensionOrOptions?: number | VectorOptions, format?: string) {
super();

if (typeof dimensionOrOptions === 'object' && dimensionOrOptions !== null) {
this.options = {
...(dimensionOrOptions.dimension !== undefined
? { dimension: this._validateDimension(dimensionOrOptions.dimension) }
: {}),
...(dimensionOrOptions.format !== undefined
? { format: this._validateFormat(dimensionOrOptions.format) }
: {}),
};

return;
}

this.options = {
...(dimensionOrOptions !== undefined
? { dimension: this._validateDimension(dimensionOrOptions) }
: {}),
...(format !== undefined ? { format: this._validateFormat(format) } : {}),
};
}

protected _getTypeName(): string {
return 'VECTOR';
}

protected _validateFormat(format: string): string {
const normalized = format.trim().toLowerCase();

switch (normalized) {
case 'float':
case 'float32':
case 'float64':
case 'int':
case 'int8':
case 'int16':
case 'int32':
case 'binary':
return normalized;
default:
throw new TypeError(`Invalid VECTOR format: ${format}`);
}
}

protected override _getSqlOptionParts(): string[] {
return [
...(this.options.dimension !== undefined ? [String(this.options.dimension)] : []),
...(this.options.format !== undefined ? [this.options.format.toUpperCase()] : []),
];
}
}

/**
* Returns true when the input is one of Sequelize's accepted numeric typed arrays.
*
* @param value
*/
function isTypedArrayIterable(value: unknown): value is NumericTypedArray {
return (
value instanceof Int8Array ||
value instanceof Uint8Array ||
value instanceof Uint8ClampedArray ||
value instanceof Int16Array ||
value instanceof Uint16Array ||
value instanceof Int32Array ||
value instanceof Uint32Array ||
value instanceof Float32Array ||
value instanceof Float64Array
);
}

function rejectBlobs(value: unknown) {
// We have a DataType called BLOB. People might try to use the built-in Blob type with it, which they cannot.
// To clarify why it doesn't work, we have a dedicated message for it.
Expand Down
2 changes: 2 additions & 0 deletions packages/core/src/abstract-dialect/dialect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ export type DialectSupports = {
GEOGRAPHY: boolean;
HSTORE: boolean;
TSVECTOR: boolean;
VECTOR: boolean;
CIDR: boolean;
INET: boolean;
MACADDR: boolean;
Expand Down Expand Up @@ -461,6 +462,7 @@ export abstract class AbstractDialect<
GEOGRAPHY: false,
HSTORE: false,
TSVECTOR: false,
VECTOR: false,
DATETIME: {
infinity: false,
},
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/abstract-dialect/query-interface.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ export interface TableNameWithSchema {

export type TableName = string | TableNameWithSchema;

export type IndexType = AllowLowercase<'UNIQUE' | 'FULLTEXT' | 'SPATIAL'>;
export type IndexType = AllowLowercase<'UNIQUE' | 'FULLTEXT' | 'SPATIAL' | 'VECTOR'>;
export type IndexMethod = 'BTREE' | 'HASH' | 'GIST' | 'SPGIST' | 'GIN' | 'BRIN' | string;

export interface IndexField {
Expand Down Expand Up @@ -116,7 +116,7 @@ export interface IndexOptions {
parser?: string | null;

/**
* Index type. Only used by mysql. One of `UNIQUE`, `FULLTEXT` and `SPATIAL`
* Index type. Used by MySQL (`UNIQUE`, `FULLTEXT`, `SPATIAL`) and Oracle (`VECTOR`).
*/
type?: IndexType | undefined;

Expand Down
2 changes: 2 additions & 0 deletions packages/core/src/data-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,5 @@ export const MACADDR8 = classToInvokable(DataTypes.MACADDR8);
export const CITEXT = classToInvokable(DataTypes.CITEXT);
/** This is a simple wrapper to make the DataType constructable without `new`. See the return type for all available options. */
export const TSVECTOR = classToInvokable(DataTypes.TSVECTOR);
/** This is a simple wrapper to make the DataType constructable without `new`. See the return type for all available options. */
export const VECTOR = classToInvokable(DataTypes.VECTOR);
52 changes: 51 additions & 1 deletion packages/core/src/sequelize.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { Options as RetryAsPromisedOptions } from 'retry-as-promised';
import type { DataTypes, Op, Options, QueryTypes } from '.';
import type { DataType } from './abstract-dialect/data-types.js';
import type { DataType, VectorValue } from './abstract-dialect/data-types.js';
import type { AbstractDialect, ConnectionOptions } from './abstract-dialect/dialect.js';
import type {
ColumnsDescription,
Expand Down Expand Up @@ -611,6 +611,56 @@ export class Sequelize<
*/
random(): Fn;

/**
* Build a dialect-specific cosine distance function.
* Dialects that advertise `DialectSupportMap.dataTypes.VECTOR` translate this generic helper
* into their native similarity operator (Oracle, Snowflake samples, pgvector, ...).
*
* @param column column name or identifier to compare against
* @param value reference vector as a plain numeric array or typed array
*/
cosineDistance(column: string, value: VectorValue): Fn;

/**
* Build a dialect-specific inner product function.
* Dialects that advertise `DialectSupportMap.dataTypes.VECTOR` translate this generic helper
* into their native similarity operator (Oracle, Snowflake samples, pgvector, ...).
*
* @param column column name or identifier to compare against
* @param value reference vector as a plain numeric array or typed array
*/
innerProduct(column: string, value: VectorValue): Fn;

/**
* Build a dialect-specific L1 distance function.
* Dialects that advertise `DialectSupportMap.dataTypes.VECTOR` translate this generic helper
* into their native similarity operator (Oracle, Snowflake samples, pgvector, ...).
*
* @param column column name or identifier to compare against
* @param value reference vector as a plain numeric array or typed array
*/
l1Distance(column: string, value: VectorValue): Fn;

/**
* Build a dialect-specific L2 distance function.
* Dialects that advertise `DialectSupportMap.dataTypes.VECTOR` translate this generic helper
* into their native similarity operator (Oracle, Snowflake samples, pgvector, ...).
*
* @param column column name or identifier to compare against
* @param value reference vector as a plain numeric array or typed array
*/
l2Distance(column: string, value: VectorValue): Fn;

/**
* Build a dialect-specific default vector distance function.
* Dialects that advertise `DialectSupportMap.dataTypes.VECTOR` translate this generic helper
* into their native similarity operator (Oracle, Snowflake samples, pgvector, ...).
*
* @param column column name or identifier to compare against
* @param value reference vector as a plain numeric array or typed array
*/
vectorDistance(column: string, value: VectorValue): Fn;

/**
* Execute a query which would set an environment or user variable. The variables are set per connection,
* so this function needs a transaction.
Expand Down
32 changes: 32 additions & 0 deletions packages/core/src/sequelize.js
Original file line number Diff line number Diff line change
Expand Up @@ -623,6 +623,38 @@ Use Sequelize#query if you wish to use replacements.`);
return sql.random;
}

cosineDistance(column, value) {
return this.#vectorSimilarityFn('COSINE_DISTANCE', column, value);
}

innerProduct(column, value) {
return this.#vectorSimilarityFn('INNER_PRODUCT', column, value);
}

l1Distance(column, value) {
return this.#vectorSimilarityFn('L1_DISTANCE', column, value);
}

l2Distance(column, value) {
return this.#vectorSimilarityFn('L2_DISTANCE', column, value);
}

vectorDistance(column, value) {
return this.#vectorSimilarityFn('VECTOR_DISTANCE', column, value);
}

#vectorSimilarityFn(fnName, column, value) {
// Dialects that advertise VECTOR support can translate these generic helper names in their
// query generator. Oracle is the primary implementation; other dialects may follow this pattern.
if (!this.dialect.supports?.dataTypes?.VECTOR) {
throw new Error(
`${fnName.toLowerCase()} for dialect "${this.dialect.name}" is not implemented`,
);
}

return fn(fnName, column, value);
}

// Global exports
static Fn = Fn;
static Col = Col;
Expand Down
Loading
Loading