metal-orm 1.1.18 → 1.1.20
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/dist/index.cjs +181 -50
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +81 -2
- package/dist/index.d.ts +81 -2
- package/dist/index.js +172 -50
- package/dist/index.js.map +1 -1
- package/package.json +6 -6
- package/src/core/ddl/dialects/mssql-schema-dialect.ts +9 -0
- package/src/core/ddl/dialects/mysql-schema-dialect.ts +5 -0
- package/src/core/ddl/dialects/postgres-schema-dialect.ts +23 -2
- package/src/core/ddl/dialects/sqlite-schema-dialect.ts +9 -0
- package/src/core/dialect/mssql/functions.ts +10 -0
- package/src/core/dialect/mysql/functions.ts +9 -0
- package/src/core/dialect/postgres/functions.ts +21 -0
- package/src/core/dialect/sqlite/functions.ts +10 -0
- package/src/core/functions/vector.ts +141 -0
- package/src/index.ts +1 -0
- package/src/schema/column-types.ts +34 -1
- package/src/schema/table.ts +6 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "metal-orm",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.20",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
},
|
|
9
9
|
"types": "./dist/index.d.ts",
|
|
10
10
|
"engines": {
|
|
11
|
-
"node": ">=
|
|
11
|
+
"node": ">=22.0.0"
|
|
12
12
|
},
|
|
13
13
|
"bin": {
|
|
14
14
|
"metal-orm-gen": "./scripts/generate-entities.mjs"
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"mysql2": "^3.22.5",
|
|
51
51
|
"pg": "^8.22.0",
|
|
52
52
|
"sqlite3": "^6.0.1",
|
|
53
|
-
"tedious": "^
|
|
53
|
+
"tedious": "^20.0.0"
|
|
54
54
|
},
|
|
55
55
|
"peerDependenciesMeta": {
|
|
56
56
|
"better-sqlite3": {
|
|
@@ -77,8 +77,8 @@
|
|
|
77
77
|
},
|
|
78
78
|
"devDependencies": {
|
|
79
79
|
"@electric-sql/pglite": "^0.5.3",
|
|
80
|
-
"@typescript-eslint/eslint-plugin": "^8.62.
|
|
81
|
-
"@typescript-eslint/parser": "^8.62.
|
|
80
|
+
"@typescript-eslint/eslint-plugin": "^8.62.1",
|
|
81
|
+
"@typescript-eslint/parser": "^8.62.1",
|
|
82
82
|
"@vitest/ui": "^4.1.9",
|
|
83
83
|
"better-sqlite3": "^12.11.1",
|
|
84
84
|
"eslint": "^10.6.0",
|
|
@@ -91,7 +91,7 @@
|
|
|
91
91
|
"pg": "^8.22.0",
|
|
92
92
|
"sqlite3": "^6.0.1",
|
|
93
93
|
"supertest": "^7.2.2",
|
|
94
|
-
"tedious": "^
|
|
94
|
+
"tedious": "^20.0.0",
|
|
95
95
|
"tsup": "^8.5.1",
|
|
96
96
|
"tsx": "^4.22.4",
|
|
97
97
|
"typescript": "^5.9.3",
|
|
@@ -73,6 +73,15 @@ export class MSSqlSchemaDialect extends BaseSchemaDialect {
|
|
|
73
73
|
return 'VARBINARY(MAX)';
|
|
74
74
|
case 'enum':
|
|
75
75
|
return 'NVARCHAR(255)';
|
|
76
|
+
case 'vector': {
|
|
77
|
+
const dim = column.vectorOptions?.dimensions ?? column.args?.[0] ?? 3;
|
|
78
|
+
const elemType = column.vectorOptions?.elementType;
|
|
79
|
+
return elemType ? `VECTOR(${dim}, ${elemType})` : `VECTOR(${dim})`;
|
|
80
|
+
}
|
|
81
|
+
case 'halfvec': {
|
|
82
|
+
const dim = column.vectorOptions?.dimensions ?? column.args?.[0] ?? 3;
|
|
83
|
+
return `VECTOR(${dim}, float16)`;
|
|
84
|
+
}
|
|
76
85
|
default:
|
|
77
86
|
return renderTypeWithArgs(String(type).toUpperCase(), column.args);
|
|
78
87
|
}
|
|
@@ -71,6 +71,11 @@ export class MySqlSchemaDialect extends BaseSchemaDialect {
|
|
|
71
71
|
return column.args && Array.isArray(column.args) && column.args.length
|
|
72
72
|
? `ENUM(${column.args.map((v: string) => `'${escapeSqlString(v)}'`).join(',')})`
|
|
73
73
|
: 'ENUM';
|
|
74
|
+
case 'vector':
|
|
75
|
+
case 'halfvec': {
|
|
76
|
+
const dim = column.vectorOptions?.dimensions ?? column.args?.[0] ?? 3;
|
|
77
|
+
return `VECTOR(${dim})`;
|
|
78
|
+
}
|
|
74
79
|
default:
|
|
75
80
|
return renderTypeWithArgs(String(type).toUpperCase(), column.args);
|
|
76
81
|
}
|
|
@@ -66,6 +66,14 @@ export class PostgresSchemaDialect extends BaseSchemaDialect {
|
|
|
66
66
|
case 'blob':
|
|
67
67
|
case 'bytea':
|
|
68
68
|
return 'bytea';
|
|
69
|
+
case 'vector':
|
|
70
|
+
return column.vectorOptions?.elementType === 'float16'
|
|
71
|
+
? `halfvec(${column.vectorOptions.dimensions})`
|
|
72
|
+
: column.args?.length
|
|
73
|
+
? `vector(${column.args[0]})`
|
|
74
|
+
: 'vector';
|
|
75
|
+
case 'halfvec':
|
|
76
|
+
return column.args?.length ? `halfvec(${column.args[0]})` : 'halfvec';
|
|
69
77
|
default:
|
|
70
78
|
return renderTypeWithArgs(String(type).toLowerCase(), column.args);
|
|
71
79
|
}
|
|
@@ -79,10 +87,23 @@ export class PostgresSchemaDialect extends BaseSchemaDialect {
|
|
|
79
87
|
|
|
80
88
|
renderIndex(table: TableDef, index: IndexDef): string {
|
|
81
89
|
const name = index.name || deriveIndexName(table, index);
|
|
82
|
-
|
|
90
|
+
let cols = renderIndexColumns(this, index.columns);
|
|
91
|
+
if (index.ops) {
|
|
92
|
+
cols = `${cols} ${index.ops}`;
|
|
93
|
+
}
|
|
83
94
|
const unique = index.unique ? 'UNIQUE ' : '';
|
|
95
|
+
const using = index.using ? ` USING ${index.using}` : '';
|
|
96
|
+
let withClause = '';
|
|
97
|
+
if (index.with) {
|
|
98
|
+
if (typeof index.with === 'string') {
|
|
99
|
+
withClause = ` WITH (${index.with})`;
|
|
100
|
+
} else {
|
|
101
|
+
const params = Object.entries(index.with).map(([k, v]) => `${k} = ${v}`).join(', ');
|
|
102
|
+
withClause = ` WITH (${params})`;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
84
105
|
const where = index.where ? ` WHERE ${index.where}` : '';
|
|
85
|
-
return `CREATE ${unique}INDEX IF NOT EXISTS ${this.quoteIdentifier(name)} ON ${this.formatTableName(table)} (${cols})${where};`;
|
|
106
|
+
return `CREATE ${unique}INDEX IF NOT EXISTS ${this.quoteIdentifier(name)} ON ${this.formatTableName(table)}${using} (${cols})${withClause}${where};`;
|
|
86
107
|
}
|
|
87
108
|
|
|
88
109
|
supportsPartialIndexes(): boolean {
|
|
@@ -57,6 +57,15 @@ export class SQLiteSchemaDialect extends BaseSchemaDialect {
|
|
|
57
57
|
case 'blob':
|
|
58
58
|
case 'bytea':
|
|
59
59
|
return 'BLOB';
|
|
60
|
+
case 'halfvec': {
|
|
61
|
+
const dim = column.vectorOptions?.dimensions ?? column.args?.[0] ?? 3;
|
|
62
|
+
return `float16[${dim}]`;
|
|
63
|
+
}
|
|
64
|
+
case 'vector': {
|
|
65
|
+
const dim = column.vectorOptions?.dimensions ?? column.args?.[0] ?? 3;
|
|
66
|
+
const elemType = column.vectorOptions?.elementType === 'float16' ? 'float16' : 'float32';
|
|
67
|
+
return `${elemType}[${dim}]`;
|
|
68
|
+
}
|
|
60
69
|
default:
|
|
61
70
|
return 'TEXT';
|
|
62
71
|
}
|
|
@@ -143,5 +143,15 @@ export class MssqlFunctionStrategy extends StandardFunctionStrategy {
|
|
|
143
143
|
this.add('ARRAY_APPEND', () => {
|
|
144
144
|
throw new Error('ARRAY_APPEND is not supported on SQL Server');
|
|
145
145
|
});
|
|
146
|
+
|
|
147
|
+
this.add('VECTOR_DISTANCE', ({ node, compiledArgs }) => {
|
|
148
|
+
if (compiledArgs.length !== 3) throw new Error('VECTOR_DISTANCE expects 3 arguments (metric, v1, v2)');
|
|
149
|
+
let metric = node.args[0]?.type === 'Literal' ? String(node.args[0].value).toLowerCase() : compiledArgs[0].replace(/['"]/g, '').toLowerCase();
|
|
150
|
+
if (metric === 'l2') metric = 'euclidean';
|
|
151
|
+
if (metric === 'l1') metric = 'manhattan';
|
|
152
|
+
if (metric === 'inner_product') metric = 'dot';
|
|
153
|
+
const [, v1, v2] = compiledArgs;
|
|
154
|
+
return `VECTOR_DISTANCE('${metric}', ${v1}, ${v2})`;
|
|
155
|
+
});
|
|
146
156
|
}
|
|
147
157
|
}
|
|
@@ -110,5 +110,14 @@ export class MysqlFunctionStrategy extends StandardFunctionStrategy {
|
|
|
110
110
|
if (compiledArgs.length !== 2) throw new Error('ARRAY_APPEND expects 2 arguments (array, value)');
|
|
111
111
|
return `JSON_ARRAY_APPEND(${compiledArgs[0]}, '$', ${compiledArgs[1]})`;
|
|
112
112
|
});
|
|
113
|
+
|
|
114
|
+
this.add('VECTOR_DISTANCE', ({ node, compiledArgs }) => {
|
|
115
|
+
if (compiledArgs.length !== 3) throw new Error('VECTOR_DISTANCE expects 3 arguments (metric, v1, v2)');
|
|
116
|
+
let metric = node.args[0]?.type === 'Literal' ? String(node.args[0].value).toUpperCase() : compiledArgs[0].replace(/['"]/g, '').toUpperCase();
|
|
117
|
+
if (metric === 'L2') metric = 'EUCLIDEAN';
|
|
118
|
+
if (metric === 'INNER_PRODUCT') metric = 'DOT';
|
|
119
|
+
const [, v1, v2] = compiledArgs;
|
|
120
|
+
return `DISTANCE(${v1}, ${v2}, '${metric}')`;
|
|
121
|
+
});
|
|
113
122
|
}
|
|
114
123
|
}
|
|
@@ -140,6 +140,27 @@ export class PostgresFunctionStrategy extends StandardFunctionStrategy {
|
|
|
140
140
|
const pathArray = this.formatJsonbPathArray(pathNode);
|
|
141
141
|
return `jsonb_set(${compiledArgs[0]}, ${pathArray}, ${compiledArgs[2]}::jsonb, true)`;
|
|
142
142
|
});
|
|
143
|
+
|
|
144
|
+
this.add('VECTOR_DISTANCE', ({ node, compiledArgs }) => {
|
|
145
|
+
if (compiledArgs.length !== 3) throw new Error('VECTOR_DISTANCE expects 3 arguments (metric, v1, v2)');
|
|
146
|
+
const metric = node.args[0]?.type === 'Literal' ? String(node.args[0].value).toLowerCase() : compiledArgs[0].replace(/['"]/g, '').toLowerCase();
|
|
147
|
+
const [, v1, v2] = compiledArgs;
|
|
148
|
+
switch (metric) {
|
|
149
|
+
case 'cosine':
|
|
150
|
+
return `(${v1} <=> ${v2})`;
|
|
151
|
+
case 'euclidean':
|
|
152
|
+
case 'l2':
|
|
153
|
+
return `(${v1} <-> ${v2})`;
|
|
154
|
+
case 'dot':
|
|
155
|
+
case 'inner_product':
|
|
156
|
+
return `(${v1} <#> ${v2})`;
|
|
157
|
+
case 'manhattan':
|
|
158
|
+
case 'l1':
|
|
159
|
+
return `(${v1} <~> ${v2})`;
|
|
160
|
+
default:
|
|
161
|
+
return `(${v1} <=> ${v2})`;
|
|
162
|
+
}
|
|
163
|
+
});
|
|
143
164
|
}
|
|
144
165
|
|
|
145
166
|
private formatJsonbPathArray(pathNode: LiteralNode): string {
|
|
@@ -151,5 +151,15 @@ export class SqliteFunctionStrategy extends StandardFunctionStrategy {
|
|
|
151
151
|
});
|
|
152
152
|
|
|
153
153
|
this.add('CHR', ({ compiledArgs }) => `CHAR(${compiledArgs[0]})`);
|
|
154
|
+
|
|
155
|
+
this.add('VECTOR_DISTANCE', ({ node, compiledArgs }) => {
|
|
156
|
+
if (compiledArgs.length !== 3) throw new Error('VECTOR_DISTANCE expects 3 arguments (metric, v1, v2)');
|
|
157
|
+
const metric = node.args[0]?.type === 'Literal' ? String(node.args[0].value).toLowerCase() : compiledArgs[0].replace(/['"]/g, '').toLowerCase();
|
|
158
|
+
const [, v1, v2] = compiledArgs;
|
|
159
|
+
if (metric === 'euclidean' || metric === 'l2') {
|
|
160
|
+
return `vec_distance_L2(${v1}, ${v2})`;
|
|
161
|
+
}
|
|
162
|
+
return `vec_distance_cosine(${v1}, ${v2})`;
|
|
163
|
+
});
|
|
154
164
|
}
|
|
155
165
|
}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
// Pure AST Builders - No Dialect Logic Here!
|
|
2
|
+
|
|
3
|
+
import { ColumnDef } from '../../schema/column-types.js';
|
|
4
|
+
import { columnOperand, valueToOperand } from '../ast/expression-builders.js';
|
|
5
|
+
import { FunctionNode, OperandNode, isOperandNode, TypedExpression, asType } from '../ast/expression.js';
|
|
6
|
+
import { BinaryExpressionNode, LogicalExpressionNode } from '../ast/expression-nodes.js';
|
|
7
|
+
import { SqlOperator } from '../sql/sql.js';
|
|
8
|
+
|
|
9
|
+
export type VectorMetric =
|
|
10
|
+
| 'cosine'
|
|
11
|
+
| 'euclidean'
|
|
12
|
+
| 'l2'
|
|
13
|
+
| 'dot'
|
|
14
|
+
| 'inner_product'
|
|
15
|
+
| 'manhattan'
|
|
16
|
+
| 'l1';
|
|
17
|
+
|
|
18
|
+
export type VectorInput =
|
|
19
|
+
| OperandNode
|
|
20
|
+
| ColumnDef
|
|
21
|
+
| number[]
|
|
22
|
+
| Float32Array
|
|
23
|
+
| string;
|
|
24
|
+
|
|
25
|
+
const isColumnDef = (val: unknown): val is ColumnDef =>
|
|
26
|
+
!!val && typeof val === 'object' && 'type' in val && 'name' in val;
|
|
27
|
+
|
|
28
|
+
const toOperand = (input: VectorInput): OperandNode => {
|
|
29
|
+
if (isOperandNode(input)) return input;
|
|
30
|
+
if (isColumnDef(input)) return columnOperand(input);
|
|
31
|
+
|
|
32
|
+
if (Array.isArray(input) || input instanceof Float32Array) {
|
|
33
|
+
const formatted = `[${Array.from(input).join(', ')}]`;
|
|
34
|
+
return valueToOperand(formatted);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return valueToOperand(input);
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const fn = (key: string, args: OperandNode[]): FunctionNode => ({
|
|
41
|
+
type: 'Function',
|
|
42
|
+
name: key,
|
|
43
|
+
fn: key,
|
|
44
|
+
args
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Calculates vector distance using a specific distance metric ('cosine', 'euclidean', 'l2', 'dot', 'inner_product', 'manhattan', 'l1').
|
|
49
|
+
* Compiles to dialect-native vector functions / operators:
|
|
50
|
+
* - SQL Server: VECTOR_DISTANCE('cosine', v1, v2)
|
|
51
|
+
* - MySQL: DISTANCE(v1, v2, 'COSINE')
|
|
52
|
+
* - PostgreSQL: (v1 <=> v2), (v1 <-> v2), (v1 <#> v2), (v1 <~> v2)
|
|
53
|
+
* - SQLite: vec_distance_cosine(v1, v2), vec_distance_L2(v1, v2)
|
|
54
|
+
*/
|
|
55
|
+
export const vectorDistance = (
|
|
56
|
+
metric: VectorMetric,
|
|
57
|
+
v1: VectorInput,
|
|
58
|
+
v2: VectorInput
|
|
59
|
+
): TypedExpression<number> => {
|
|
60
|
+
const metricOp = valueToOperand(metric.toLowerCase());
|
|
61
|
+
return asType<number>(fn('VECTOR_DISTANCE', [metricOp, toOperand(v1), toOperand(v2)]));
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Calculates Cosine distance between two vectors.
|
|
66
|
+
*/
|
|
67
|
+
export const cosineDistance = (v1: VectorInput, v2: VectorInput): TypedExpression<number> =>
|
|
68
|
+
vectorDistance('cosine', v1, v2);
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Calculates Euclidean (L2) distance between two vectors.
|
|
72
|
+
*/
|
|
73
|
+
export const l2Distance = (v1: VectorInput, v2: VectorInput): TypedExpression<number> =>
|
|
74
|
+
vectorDistance('euclidean', v1, v2);
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Alias for l2Distance. Calculates Euclidean distance between two vectors.
|
|
78
|
+
*/
|
|
79
|
+
export const euclideanDistance = (v1: VectorInput, v2: VectorInput): TypedExpression<number> =>
|
|
80
|
+
vectorDistance('euclidean', v1, v2);
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Calculates Inner / Dot product distance between two vectors.
|
|
84
|
+
*/
|
|
85
|
+
export const innerProduct = (v1: VectorInput, v2: VectorInput): TypedExpression<number> =>
|
|
86
|
+
vectorDistance('dot', v1, v2);
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Alias for innerProduct. Calculates Dot product distance between two vectors.
|
|
90
|
+
*/
|
|
91
|
+
export const dotProduct = (v1: VectorInput, v2: VectorInput): TypedExpression<number> =>
|
|
92
|
+
vectorDistance('dot', v1, v2);
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Calculates Manhattan (L1) distance between two vectors.
|
|
96
|
+
*/
|
|
97
|
+
export const l1Distance = (v1: VectorInput, v2: VectorInput): TypedExpression<number> =>
|
|
98
|
+
vectorDistance('manhattan', v1, v2);
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Alias for l1Distance. Calculates Manhattan distance between two vectors.
|
|
102
|
+
*/
|
|
103
|
+
export const manhattanDistance = (v1: VectorInput, v2: VectorInput): TypedExpression<number> =>
|
|
104
|
+
vectorDistance('manhattan', v1, v2);
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Builds a SQLite `sqlite-vec` KNN virtual table query predicate:
|
|
108
|
+
* `col MATCH '[...]' AND k = n`
|
|
109
|
+
*
|
|
110
|
+
* @param column - The vector virtual table column to match against.
|
|
111
|
+
* @param vector - The query vector(s) to match (raw array/string is inlined as a literal).
|
|
112
|
+
* @param k - Number of nearest neighbors to return.
|
|
113
|
+
*
|
|
114
|
+
* @example
|
|
115
|
+
* ```ts
|
|
116
|
+
* where(vectorMatch(items.embedding, [0.1, 2, 30], 5))
|
|
117
|
+
* // => "embedding" MATCH '[0.1, 2, 30]' AND k = 5
|
|
118
|
+
* ```
|
|
119
|
+
*/
|
|
120
|
+
export const vectorMatch = (
|
|
121
|
+
column: VectorInput,
|
|
122
|
+
vector: VectorInput,
|
|
123
|
+
k: number
|
|
124
|
+
): LogicalExpressionNode => {
|
|
125
|
+
const match: BinaryExpressionNode = {
|
|
126
|
+
type: 'BinaryExpression',
|
|
127
|
+
left: toOperand(column),
|
|
128
|
+
operator: 'MATCH' as SqlOperator,
|
|
129
|
+
right: toOperand(vector)
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
const kNode: BinaryExpressionNode = {
|
|
133
|
+
type: 'BinaryExpression',
|
|
134
|
+
left: valueToOperand('k'),
|
|
135
|
+
operator: '=',
|
|
136
|
+
right: valueToOperand(k)
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
return { type: 'LogicalExpression', operator: 'AND', operands: [match, kNode] };
|
|
140
|
+
};
|
|
141
|
+
|
package/src/index.ts
CHANGED
|
@@ -32,6 +32,7 @@ export * from './core/functions/datetime.js';
|
|
|
32
32
|
export * from './core/functions/control-flow.js';
|
|
33
33
|
export * from './core/functions/json.js';
|
|
34
34
|
export * from './core/functions/array.js';
|
|
35
|
+
export * from './core/functions/vector.js';
|
|
35
36
|
export * from './orm/als.js';
|
|
36
37
|
export * from './orm/hydration.js';
|
|
37
38
|
export * from './codegen/typescript.js';
|
|
@@ -21,7 +21,9 @@ export const STANDARD_COLUMN_TYPES = [
|
|
|
21
21
|
'DATETIME',
|
|
22
22
|
'TIMESTAMP',
|
|
23
23
|
'TIMESTAMPTZ',
|
|
24
|
-
'BOOLEAN'
|
|
24
|
+
'BOOLEAN',
|
|
25
|
+
'VECTOR',
|
|
26
|
+
'HALFVEC'
|
|
25
27
|
] as const;
|
|
26
28
|
|
|
27
29
|
/** Known logical types the ORM understands. */
|
|
@@ -113,6 +115,11 @@ export interface ColumnDef<T extends ColumnType = ColumnType, TRuntime = unknown
|
|
|
113
115
|
comment?: string;
|
|
114
116
|
/** Additional arguments for the column type (e.g., VARCHAR length) */
|
|
115
117
|
args?: (string | number)[];
|
|
118
|
+
/** Options specific to vector columns (dimensions, float16 vs float32, etc.) */
|
|
119
|
+
vectorOptions?: {
|
|
120
|
+
dimensions: number;
|
|
121
|
+
elementType?: 'float16' | 'float32' | 'int8' | 'bit';
|
|
122
|
+
};
|
|
116
123
|
/** Table name this column belongs to (filled at runtime by defineTable) */
|
|
117
124
|
table?: string;
|
|
118
125
|
}
|
|
@@ -236,6 +243,32 @@ export const col = {
|
|
|
236
243
|
*/
|
|
237
244
|
enum: (values: string[]): ColumnDef<'ENUM'> => ({ name: '', type: 'ENUM', args: values }),
|
|
238
245
|
|
|
246
|
+
/**
|
|
247
|
+
* Creates a vector column definition
|
|
248
|
+
* @param dimensions - Vector dimensions
|
|
249
|
+
* @param options - Vector options (e.g. elementType: 'float16' | 'float32')
|
|
250
|
+
*/
|
|
251
|
+
vector: (
|
|
252
|
+
dimensions: number,
|
|
253
|
+
options?: { elementType?: 'float16' | 'float32' | 'int8' | 'bit' }
|
|
254
|
+
): ColumnDef<'VECTOR', number[]> => ({
|
|
255
|
+
name: '',
|
|
256
|
+
type: 'VECTOR',
|
|
257
|
+
args: [dimensions],
|
|
258
|
+
vectorOptions: { dimensions, ...options }
|
|
259
|
+
}),
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Creates a half-precision (float16) vector column definition (pgvector halfvec / SQL Server float16 vector / sqlite-vec float16)
|
|
263
|
+
* @param dimensions - Vector dimensions
|
|
264
|
+
*/
|
|
265
|
+
halfvec: (dimensions: number): ColumnDef<'HALFVEC', number[]> => ({
|
|
266
|
+
name: '',
|
|
267
|
+
type: 'HALFVEC',
|
|
268
|
+
args: [dimensions],
|
|
269
|
+
vectorOptions: { dimensions, elementType: 'float16' }
|
|
270
|
+
}),
|
|
271
|
+
|
|
239
272
|
/**
|
|
240
273
|
* Creates a column definition with a custom SQL type.
|
|
241
274
|
* Useful for dialect-specific types without polluting the standard set.
|
package/src/schema/table.ts
CHANGED
|
@@ -12,6 +12,12 @@ export interface IndexDef {
|
|
|
12
12
|
columns: (string | IndexColumn)[];
|
|
13
13
|
unique?: boolean;
|
|
14
14
|
where?: string;
|
|
15
|
+
/** Index method / access method, e.g. 'hnsw', 'ivfflat', 'btree' */
|
|
16
|
+
using?: string;
|
|
17
|
+
/** Operator class for vector distance, e.g. 'vector_cosine_ops', 'vector_l2_ops', 'halfvec_cosine_ops' */
|
|
18
|
+
ops?: string;
|
|
19
|
+
/** Index parameters / WITH clause options, e.g. { m: 16, ef_construction: 64 } */
|
|
20
|
+
with?: Record<string, unknown> | string;
|
|
15
21
|
}
|
|
16
22
|
|
|
17
23
|
export interface CheckConstraint {
|