@an5/adapters 0.2.11 → 0.2.14
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 +137 -5
- package/dist/an5Adapter.d.ts +42 -1
- package/dist/an5Adapter.js +146 -38
- package/dist/base/types.d.ts +14 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +8 -1
- package/dist/sqlite/browserEngine.d.ts +13 -0
- package/dist/sqlite/browserEngine.js +13 -0
- package/dist/sqlite/engine.d.ts +5 -0
- package/dist/sqlite/engine.js +10 -0
- package/dist/sqlite/index.d.ts +1 -0
- package/dist/sqlite/index.js +1 -0
- package/dist/sqlite/vector.d.ts +155 -0
- package/dist/sqlite/vector.js +432 -0
- package/dotnet/An5Adapter.cs +99 -28
- package/dotnet/Base/Core.cs +14 -0
- package/dotnet/Mssql/MssqlEngine.cs +44 -1
- package/dotnet/Postgres/PostgresEngine.cs +2 -0
- package/dotnet/Sqlite/SqliteEngine.cs +82 -2
- package/dotnet/Sqlite/SqliteVectors.cs +401 -0
- package/golang/an5_adapter.go +84 -32
- package/golang/base/vectors.go +263 -0
- package/golang/sqlite/vector.go +248 -0
- package/golang/sqlite_vector_test.go +288 -0
- package/golang/table_client.go +67 -3
- package/java/pom.xml +177 -0
- package/java/src/main/java/an5/adapters/An5Adapter.java +374 -0
- package/java/src/main/java/an5/adapters/An5Aggregate.java +116 -0
- package/java/src/main/java/an5/adapters/An5GroupBy.java +97 -0
- package/java/src/main/java/an5/adapters/An5Query.java +100 -0
- package/java/src/main/java/an5/adapters/An5TableClient.java +1030 -0
- package/java/src/main/java/an5/adapters/An5ViewClient.java +107 -0
- package/java/src/main/java/an5/adapters/base/Dialect.java +103 -0
- package/java/src/main/java/an5/adapters/base/FieldMeta.java +42 -0
- package/java/src/main/java/an5/adapters/base/JdbcUrls.java +201 -0
- package/java/src/main/java/an5/adapters/base/Metadata.java +195 -0
- package/java/src/main/java/an5/adapters/base/RelationDef.java +26 -0
- package/java/src/main/java/an5/adapters/base/SqlBuilder.java +422 -0
- package/java/src/main/java/an5/adapters/base/SqliteVectors.java +375 -0
- package/java/src/main/java/an5/adapters/base/Vectors.java +123 -0
- package/java/src/test/java/An5AdaptersSmoke.java +733 -0
- package/java/src/test/java/Json.java +174 -0
- package/java/src/test/java/QuerySemantics.java +111 -0
- package/kotlin/build.gradle.kts +145 -0
- package/kotlin/settings.gradle.kts +10 -0
- package/kotlin/src/main/kotlin/an5/adapters/Aggregate.kt +89 -0
- package/kotlin/src/main/kotlin/an5/adapters/An5.kt +91 -0
- package/kotlin/src/main/kotlin/an5/adapters/Query.kt +130 -0
- package/kotlin/src/main/kotlin/an5/adapters/Rows.kt +166 -0
- package/kotlin/src/main/kotlin/an5/adapters/TableClient.kt +169 -0
- package/kotlin/src/main/kotlin/an5/adapters/Types.kt +77 -0
- package/kotlin/src/test/kotlin/an5/adapters/An5Smoke.kt +329 -0
- package/native/sqlite/CMakeLists.txt +12 -0
- package/native/sqlite/README.md +117 -0
- package/native/sqlite/an5_vector.c +209 -0
- package/package.json +33 -7
- package/python/an5_adapter.py +37 -6
- package/python/base/__init__.py +15 -0
- package/python/base/vectors.py +431 -0
- package/python/sqlite/__init__.py +2 -2
- package/python/sqlite/provider.py +21 -1
- package/python/table_client.py +129 -59
- package/rust/src/adapter.rs +342 -24
- package/rust/src/base/mod.rs +7 -0
- package/rust/src/base/vectors.rs +293 -0
- package/rust/src/lib.rs +3 -3
- package/scripts/sqlite-native-build.js +32 -0
- package/swift/Package.swift +22 -0
- package/swift/Sources/An5Adapters/An5Adapter.swift +160 -0
- package/swift/Sources/An5Adapters/Metadata.swift +183 -0
- package/swift/Sources/An5Adapters/Query.swift +105 -0
- package/swift/Sources/An5Adapters/Row+Accessors.swift +129 -0
- package/swift/Sources/An5Adapters/SQLBuilder.swift +359 -0
- package/swift/Sources/An5Adapters/SQLiteDriver.swift +301 -0
- package/swift/Sources/An5Adapters/SqliteVectors.swift +243 -0
- package/swift/Sources/An5Adapters/TableClient.swift +671 -0
- package/swift/Sources/An5Adapters/Types.swift +127 -0
- package/swift/Sources/An5Adapters/Vectors.swift +86 -0
- package/swift/Sources/An5Adapters/ViewClient.swift +50 -0
- package/swift/Sources/CSQLite/module.modulemap +8 -0
- package/swift/Sources/CSQLite/shim.h +9 -0
- package/swift/Tests/An5AdaptersTests/QuerySemanticsTests.swift +51 -0
- package/swift/Tests/An5AdaptersTests/RuntimeSmokeTests.swift +488 -0
- package/typescript/src/an5Adapter.ts +155 -31
- package/typescript/src/base/types.ts +15 -0
- package/typescript/src/index.ts +13 -0
- package/typescript/src/sqlite/browserEngine.ts +24 -0
- package/typescript/src/sqlite/engine.ts +13 -0
- package/typescript/src/sqlite/index.ts +1 -1
- package/typescript/src/sqlite/vector.ts +537 -0
- package/golang/sqlite/sqlite.go +0 -14
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Dialect, QueryEngine, TransactionHandle } from '../base/types';
|
|
2
|
+
import { SqliteVectorSupport } from './vector';
|
|
2
3
|
export interface SqliteDriver {
|
|
3
4
|
exec<T = any>(query: string, params?: Record<string, any>): Promise<T[]> | T[];
|
|
4
5
|
executeRaw?(query: string, params?: Record<string, any>): Promise<number> | number;
|
|
@@ -9,9 +10,21 @@ export interface SqliteBrowserConfig {
|
|
|
9
10
|
driver?: SqliteDriver;
|
|
10
11
|
exec?: <T = any>(query: string, params?: Record<string, any>) => Promise<T[]> | T[];
|
|
11
12
|
executeRaw?: (query: string, params?: Record<string, any>) => Promise<number> | number;
|
|
13
|
+
/** Path to the sqlite-vec extension, for WASM builds that allow loading one. */
|
|
14
|
+
sqliteVec?: string;
|
|
15
|
+
/** Pin the vector search strategy instead of probing for one. */
|
|
16
|
+
vectorStrategy?: 'auto' | 'sqlite-vec' | 'udf' | 'sql' | 'memory';
|
|
17
|
+
/** Register a scalar function with the driver, when its API allows it. */
|
|
18
|
+
registerFunction?: (name: string, fn: (...args: any[]) => any) => void;
|
|
12
19
|
}
|
|
13
20
|
export declare class SqliteBrowserEngine implements QueryEngine {
|
|
14
21
|
dialect: Dialect;
|
|
22
|
+
/**
|
|
23
|
+
* A WASM build cannot register a JS callback as an SQL function, so this only
|
|
24
|
+
* reaches the `sql` strategy (json_each in plain SQL) and the in-memory one.
|
|
25
|
+
* A custom `registerFunction` hook unlocks `udf` as well.
|
|
26
|
+
*/
|
|
27
|
+
readonly vectorSupport: SqliteVectorSupport;
|
|
15
28
|
private db;
|
|
16
29
|
private driver;
|
|
17
30
|
private customExec;
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.SqliteBrowserEngine = void 0;
|
|
4
4
|
exports.createBrowserSqliteAdapter = createBrowserSqliteAdapter;
|
|
5
|
+
const vector_1 = require("./vector");
|
|
5
6
|
// ─── Browser SQLite Engine ──────────────────────────────────────────────────────────
|
|
6
7
|
class SqliteBrowserEngine {
|
|
7
8
|
constructor(config) {
|
|
@@ -10,6 +11,18 @@ class SqliteBrowserEngine {
|
|
|
10
11
|
this.driver = null;
|
|
11
12
|
this.customExec = null;
|
|
12
13
|
this.customExecuteRaw = null;
|
|
14
|
+
this.vectorSupport = new vector_1.SqliteVectorSupport({
|
|
15
|
+
native: () => this.db,
|
|
16
|
+
registerFunction: (name, fn) => {
|
|
17
|
+
const register = config?.registerFunction;
|
|
18
|
+
if (typeof register === 'function')
|
|
19
|
+
return register(name, fn);
|
|
20
|
+
const db = this.db;
|
|
21
|
+
if (db && typeof db.create_function === 'function')
|
|
22
|
+
return db.create_function(name, fn);
|
|
23
|
+
throw new Error('this SQLite build cannot register functions');
|
|
24
|
+
},
|
|
25
|
+
}, { sqliteVec: config?.sqliteVec, vectorStrategy: config?.vectorStrategy });
|
|
13
26
|
if (!config)
|
|
14
27
|
return;
|
|
15
28
|
if (config.exec && typeof config.exec === 'function') {
|
package/dist/sqlite/engine.d.ts
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
import type { An5AdapterConfig, Dialect, QueryEngine, TransactionHandle } from '../base/types';
|
|
2
|
+
import { SqliteVectorSupport } from './vector';
|
|
2
3
|
export declare class SqliteEngine implements QueryEngine {
|
|
3
4
|
dialect: Dialect;
|
|
5
|
+
/** Registers `an5_vec_*` and loads sqlite-vec for in-database vector search. */
|
|
6
|
+
readonly vectorSupport: SqliteVectorSupport;
|
|
4
7
|
private db;
|
|
5
8
|
private readonly filePath;
|
|
6
9
|
constructor(adapterConfig: An5AdapterConfig);
|
|
10
|
+
/** The better-sqlite3 handle, needed for extension loading. */
|
|
11
|
+
native(): any;
|
|
7
12
|
private getDb;
|
|
8
13
|
exec<T = any>(query: string, params?: Record<string, any>): Promise<T[]>;
|
|
9
14
|
executeRaw(query: string, params?: Record<string, any>): Promise<number>;
|
package/dist/sqlite/engine.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.SqliteEngine = void 0;
|
|
4
|
+
const vector_1 = require("./vector");
|
|
4
5
|
// ─── SQLite Engine ─────────────────────────────────────────────────────────────────
|
|
5
6
|
let BetterSqlite3 = null;
|
|
6
7
|
try {
|
|
@@ -17,6 +18,14 @@ class SqliteEngine {
|
|
|
17
18
|
.replace(/^sqlite:\/\/\//i, '/')
|
|
18
19
|
.replace(/^sqlite:\/\//i, '')
|
|
19
20
|
.replace(/^sqlite:/i, '');
|
|
21
|
+
this.vectorSupport = new vector_1.SqliteVectorSupport({
|
|
22
|
+
native: () => this.getDb(),
|
|
23
|
+
registerFunction: (name, fn) => this.getDb().function(name, { deterministic: true }, fn),
|
|
24
|
+
}, { sqliteVec: adapterConfig.sqliteVec, vectorStrategy: adapterConfig.vectorStrategy });
|
|
25
|
+
}
|
|
26
|
+
/** The better-sqlite3 handle, needed for extension loading. */
|
|
27
|
+
native() {
|
|
28
|
+
return this.getDb();
|
|
20
29
|
}
|
|
21
30
|
getDb() {
|
|
22
31
|
if (!this.db)
|
|
@@ -42,6 +51,7 @@ class SqliteEngine {
|
|
|
42
51
|
this.db.close();
|
|
43
52
|
this.db = null;
|
|
44
53
|
}
|
|
54
|
+
this.vectorSupport.reset();
|
|
45
55
|
}
|
|
46
56
|
async beginTransaction() {
|
|
47
57
|
const db = this.getDb();
|
package/dist/sqlite/index.d.ts
CHANGED
package/dist/sqlite/index.js
CHANGED
|
@@ -16,3 +16,4 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
__exportStar(require("./engine"), exports);
|
|
18
18
|
__exportStar(require("./browserEngine"), exports);
|
|
19
|
+
__exportStar(require("./vector"), exports);
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
export type VectorMetric = 'cosine' | 'euclidean' | 'dot';
|
|
2
|
+
export type SqliteVectorStrategy = 'sqlite-vec' | 'udf' | 'sql' | 'memory';
|
|
3
|
+
export type VectorStrategyPreference = 'auto' | SqliteVectorStrategy;
|
|
4
|
+
/** Scalar functions shipped by the sqlite-vec extension. */
|
|
5
|
+
export declare const SQLITE_VEC_FUNCTIONS: Record<VectorMetric, string>;
|
|
6
|
+
/** Scalar functions the adapter registers itself when the driver allows it. */
|
|
7
|
+
export declare const AN5_VECTOR_FUNCTIONS: Record<VectorMetric, string>;
|
|
8
|
+
/** Read a numeric array out of the shapes a driver can hand back. */
|
|
9
|
+
export declare function parseVector(value: unknown): number[] | null;
|
|
10
|
+
/**
|
|
11
|
+
* Decode a stored vector: a float32 BLOB, a legacy JSON text column, or an
|
|
12
|
+
* array the caller already decoded.
|
|
13
|
+
*/
|
|
14
|
+
export declare function decodeVector(value: unknown): number[] | null;
|
|
15
|
+
/** Encode a vector as the little-endian float32 BLOB `VECTOR(n)` columns store. */
|
|
16
|
+
export declare function encodeVector(values: readonly number[]): Uint8Array;
|
|
17
|
+
/** True when the value still needs encoding on its way into a `VECTOR(n)` column. */
|
|
18
|
+
export declare function needsVectorEncoding(value: unknown): boolean;
|
|
19
|
+
/** True when a generated metadata entry describes a `VECTOR(n)` column. */
|
|
20
|
+
export declare function isVectorField(def: unknown): boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Distance between two equal-length vectors, lower is closer. Mirrors the
|
|
23
|
+
* functions registered on the drivers so a search ranks the same way whichever
|
|
24
|
+
* strategy ran.
|
|
25
|
+
*/
|
|
26
|
+
export declare function vectorDistance(a: readonly number[], b: readonly number[], metric: unknown): number | null;
|
|
27
|
+
export interface SqliteVectorQuery {
|
|
28
|
+
sql: string;
|
|
29
|
+
params: Record<string, any>;
|
|
30
|
+
}
|
|
31
|
+
interface BuildArgs {
|
|
32
|
+
strategy: SqliteVectorStrategy;
|
|
33
|
+
metric: VectorMetric;
|
|
34
|
+
/** Already quoted, e.g. `[documents]`. */
|
|
35
|
+
table: string;
|
|
36
|
+
/** Already quoted column reference. */
|
|
37
|
+
column: string;
|
|
38
|
+
/** The query embedding. */
|
|
39
|
+
vector: number[];
|
|
40
|
+
take: number;
|
|
41
|
+
/** A WHERE tail built by the caller, or empty. */
|
|
42
|
+
tail?: string;
|
|
43
|
+
/** Pre-bound WHERE parameters shared with the caller. */
|
|
44
|
+
params: Record<string, any>;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Ranking SQL for one strategy. `sqlite-vec` and `udf` bind the query vector as
|
|
48
|
+
* a float32 BLOB; `sql` binds it as JSON text because `json_each` reads text.
|
|
49
|
+
*/
|
|
50
|
+
export declare function buildSqliteVectorQuery(args: BuildArgs): SqliteVectorQuery;
|
|
51
|
+
export interface SqliteVectorCapabilities {
|
|
52
|
+
/** AN5's C extension is loaded; keep its functions instead of driver callbacks. */
|
|
53
|
+
native?: boolean;
|
|
54
|
+
/** `vec_version()` answered, so the sqlite-vec extension is loaded. */
|
|
55
|
+
vec: boolean;
|
|
56
|
+
/** The adapter's own distance functions are registered with the driver. */
|
|
57
|
+
udf: boolean;
|
|
58
|
+
/** `json_each()` is available, which the pure-SQL strategy needs. */
|
|
59
|
+
json1: boolean;
|
|
60
|
+
}
|
|
61
|
+
export interface SqliteVectorOptions {
|
|
62
|
+
/** Path to the sqlite-vec extension binary to load before probing. */
|
|
63
|
+
sqliteVec?: string | undefined;
|
|
64
|
+
/** Pin a strategy instead of probing for the fastest one available. */
|
|
65
|
+
vectorStrategy?: VectorStrategyPreference | undefined;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* A driver hook the engine can supply to register the distance functions and
|
|
69
|
+
* load the sqlite-vec extension. Every field is optional: a driver that offers
|
|
70
|
+
* nothing simply reports no capabilities and the search falls back.
|
|
71
|
+
*/
|
|
72
|
+
/**
|
|
73
|
+
* Registers a scalar function with the driver. Implementations that take a
|
|
74
|
+
* determinism flag (better-sqlite3) supply it themselves.
|
|
75
|
+
*/
|
|
76
|
+
export type SqliteVectorFunctionRegistrar = (name: string, fn: (...args: any[]) => any) => void;
|
|
77
|
+
export interface SqliteVectorHooks {
|
|
78
|
+
/** Raw driver handle, used for `loadExtension`. */
|
|
79
|
+
native?: () => any;
|
|
80
|
+
/** Register `name` with the driver's scalar-function API. */
|
|
81
|
+
registerFunction?: SqliteVectorFunctionRegistrar;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Resolve the ordered list of strategies to try for this connection.
|
|
85
|
+
*
|
|
86
|
+
* `declaredType` is the column's DDL type: the JSON strategy only reaches rows
|
|
87
|
+
* stored as text, so a `BLOB` column drops it from the order.
|
|
88
|
+
*/
|
|
89
|
+
export declare function planSqliteVectorStrategies(caps: SqliteVectorCapabilities, declaredType: string | null, preference?: VectorStrategyPreference): SqliteVectorStrategy[];
|
|
90
|
+
/**
|
|
91
|
+
* Register `an5_vec_*` on a driver and load sqlite-vec when a path is configured.
|
|
92
|
+
* Safe to call repeatedly; each driver hook is used at most once.
|
|
93
|
+
*/
|
|
94
|
+
export declare class SqliteVectorSupport {
|
|
95
|
+
private readonly hooks;
|
|
96
|
+
private readonly options;
|
|
97
|
+
private caps;
|
|
98
|
+
/**
|
|
99
|
+
* Declared column types and the "any binary row" probe, keyed by column.
|
|
100
|
+
*
|
|
101
|
+
* Both cost a query, and neither changes while a schema is in use. A stale
|
|
102
|
+
* answer is still safe: the probe only decides which strategy to try first, and
|
|
103
|
+
* a strategy that fails falls through to the next one rather than reporting a
|
|
104
|
+
* wrong result.
|
|
105
|
+
*/
|
|
106
|
+
private readonly columnTypes;
|
|
107
|
+
private readonly binaryRows;
|
|
108
|
+
constructor(hooks: SqliteVectorHooks, options?: SqliteVectorOptions);
|
|
109
|
+
capabilities(): Promise<SqliteVectorCapabilities>;
|
|
110
|
+
/** Confirms JSON1 and a usable sqlite-vec/UDF before a query is built for them. */
|
|
111
|
+
probe(exec: (sql: string, params?: Record<string, any>) => Promise<any[]>): Promise<SqliteVectorCapabilities>;
|
|
112
|
+
/** The column's declared DDL type, remembered per column. */
|
|
113
|
+
columnType(exec: (sql: string, params?: Record<string, any>) => Promise<any[]>, table: string, column: string): Promise<string | null>;
|
|
114
|
+
/**
|
|
115
|
+
* Whether any row stores raw bytes, which `json_each` cannot read.
|
|
116
|
+
*
|
|
117
|
+
* Checked only for the `sql` strategy, where a legacy JSON column that has
|
|
118
|
+
* since taken new float32 rows would otherwise rank just the old ones.
|
|
119
|
+
*/
|
|
120
|
+
hasBinaryRows(exec: (sql: string, params?: Record<string, any>) => Promise<any[]>, table: string, column: string, tail: string, params: Record<string, any>): Promise<boolean>;
|
|
121
|
+
reset(): void;
|
|
122
|
+
}
|
|
123
|
+
/** Reads a vector column's declared DDL type, or null when it cannot be found. */
|
|
124
|
+
export declare function readSqliteColumnType(exec: (sql: string, params?: Record<string, any>) => Promise<any[]>, table: string, column: string): Promise<string | null>;
|
|
125
|
+
export interface SqliteVectorSearchArgs {
|
|
126
|
+
exec: (sql: string, params?: Record<string, any>) => Promise<any[]>;
|
|
127
|
+
/** Absent when the engine cannot register functions or load extensions. */
|
|
128
|
+
vectorSupport?: SqliteVectorSupport | null;
|
|
129
|
+
/** Quoted table reference, e.g. `[documents]`. */
|
|
130
|
+
table: string;
|
|
131
|
+
/** Unquoted table name, for `pragma_table_info`. */
|
|
132
|
+
rawTable: string;
|
|
133
|
+
/** Quoted column reference. */
|
|
134
|
+
column: string;
|
|
135
|
+
/** Unquoted column name. */
|
|
136
|
+
rawColumn: string;
|
|
137
|
+
vector: number[];
|
|
138
|
+
metric: VectorMetric;
|
|
139
|
+
take: number;
|
|
140
|
+
/** A WHERE tail (leading space included) or empty. */
|
|
141
|
+
tail?: string | undefined;
|
|
142
|
+
/** Parameter object shared with the caller's WHERE clause. */
|
|
143
|
+
params: Record<string, any>;
|
|
144
|
+
preference?: VectorStrategyPreference | undefined;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Rank a SQLite table by distance inside the database, trying each available
|
|
148
|
+
* strategy in order. Returns null when the connection offers none, so the
|
|
149
|
+
* caller can fall back to scoring in memory.
|
|
150
|
+
*/
|
|
151
|
+
export declare function runSqliteVectorSearch(args: SqliteVectorSearchArgs): Promise<{
|
|
152
|
+
rows: Record<string, any>[];
|
|
153
|
+
strategy: SqliteVectorStrategy;
|
|
154
|
+
} | null>;
|
|
155
|
+
export {};
|