uql-orm 0.21.0 → 0.22.0
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 +5 -4
- package/dist/bunSql/bunSqlCockroachDialect.d.ts +2 -2
- package/dist/bunSql/bunSqlCockroachDialect.js +4 -10
- package/dist/bunSql/bunSqlPostgresDialect.d.ts +2 -2
- package/dist/bunSql/bunSqlPostgresDialect.js +4 -10
- package/dist/cockroachdb/cockroachDialect.d.ts +20 -4
- package/dist/cockroachdb/cockroachDialect.js +33 -18
- package/dist/d1/d1Querier.d.ts +4 -3
- package/dist/d1/d1Querier.js +0 -3
- package/dist/d1/d1SqliteDialect.d.ts +7 -0
- package/dist/d1/d1SqliteDialect.js +9 -0
- package/dist/dialect/abstractDialect.d.ts +8 -3
- package/dist/dialect/abstractDialect.js +9 -4
- package/dist/dialect/abstractSqlDialect.d.ts +35 -7
- package/dist/dialect/abstractSqlDialect.js +76 -35
- package/dist/dialect/index.d.ts +1 -0
- package/dist/dialect/index.js +1 -0
- package/dist/dialect/indexSqlDialect.d.ts +57 -0
- package/dist/dialect/indexSqlDialect.js +101 -0
- package/dist/dialect/mysqlLikeSqlDialect.d.ts +16 -1
- package/dist/dialect/mysqlLikeSqlDialect.js +32 -1
- package/dist/dialect/pgLikeSqlDialect.d.ts +33 -15
- package/dist/dialect/pgLikeSqlDialect.js +90 -56
- package/dist/dialect/vectorCast.d.ts +21 -0
- package/dist/dialect/vectorCast.js +28 -0
- package/dist/dialect/vectorSqlDialect.d.ts +10 -3
- package/dist/dialect/vectorSqlDialect.js +19 -8
- package/dist/entity/decorator/index-decorator.d.ts +2 -9
- package/dist/entity/metadata/definition.d.ts +5 -4
- package/dist/entity/metadata/definition.js +4 -3
- package/dist/libsql/libsqlDialect.d.ts +12 -2
- package/dist/libsql/libsqlDialect.js +14 -2
- package/dist/libsql/libsqlQuerier.d.ts +9 -22
- package/dist/libsql/libsqlQuerier.js +9 -85
- package/dist/libsql/libsqlQuerierPool.d.ts +10 -8
- package/dist/libsql/libsqlQuerierPool.js +17 -15
- package/dist/maria/mariaDialect.d.ts +26 -4
- package/dist/maria/mariaDialect.js +54 -15
- package/dist/migrate/builder/migrationBuilder.d.ts +9 -29
- package/dist/migrate/builder/migrationBuilder.js +58 -76
- package/dist/migrate/builder/splitSqlStatements.d.ts +0 -2
- package/dist/migrate/builder/splitSqlStatements.js +0 -2
- package/dist/migrate/builder/tableBuilder.d.ts +12 -2
- package/dist/migrate/builder/tableBuilder.js +71 -119
- package/dist/migrate/builder/types.d.ts +30 -41
- package/dist/migrate/cli.d.ts +3 -2
- package/dist/migrate/cli.js +21 -48
- package/dist/migrate/codegen/entityCodeGenerator.d.ts +0 -4
- package/dist/migrate/codegen/entityCodeGenerator.js +5 -63
- package/dist/migrate/codegen/fieldOptionsSource.d.ts +10 -0
- package/dist/migrate/codegen/fieldOptionsSource.js +55 -0
- package/dist/migrate/codegen/index.d.ts +0 -2
- package/dist/migrate/codegen/index.js +0 -4
- package/dist/migrate/generator/indexNodeToSchema.d.ts +9 -0
- package/dist/migrate/generator/indexNodeToSchema.js +14 -0
- package/dist/migrate/generator/mongoCommand.d.ts +57 -0
- package/dist/migrate/generator/mongoCommand.js +26 -0
- package/dist/migrate/generator/mongoSchemaGenerator.d.ts +9 -20
- package/dist/migrate/generator/mongoSchemaGenerator.js +40 -82
- package/dist/migrate/index.d.ts +0 -1
- package/dist/migrate/index.js +0 -1
- package/dist/migrate/introspection/abstractSqlSchemaIntrospector.d.ts +25 -10
- package/dist/migrate/introspection/abstractSqlSchemaIntrospector.js +46 -32
- package/dist/migrate/introspection/baseSqlIntrospector.d.ts +0 -1
- package/dist/migrate/introspection/baseSqlIntrospector.js +3 -12
- package/dist/migrate/introspection/mongoIntrospector.js +2 -2
- package/dist/migrate/introspection/mysqlIntrospector.d.ts +5 -8
- package/dist/migrate/introspection/mysqlIntrospector.js +4 -10
- package/dist/migrate/introspection/postgresIntrospector.d.ts +5 -8
- package/dist/migrate/introspection/postgresIntrospector.js +4 -10
- package/dist/migrate/introspection/sqliteIntrospector.d.ts +6 -5
- package/dist/migrate/introspection/sqliteIntrospector.js +26 -18
- package/dist/migrate/migrator.d.ts +23 -3
- package/dist/migrate/migrator.js +57 -69
- package/dist/migrate/schemaGenerator.d.ts +26 -37
- package/dist/migrate/schemaGenerator.js +69 -174
- package/dist/migrate/schemaGeneratorAsync.d.ts +2 -2
- package/dist/migrate/schemaGeneratorAsync.js +3 -3
- package/dist/migrate/storage/databaseStorage.js +4 -4
- package/dist/mongo/mongoDialect.d.ts +2 -0
- package/dist/mongo/mongoDialect.js +14 -3
- package/dist/mysql/mysqlDialect.d.ts +8 -0
- package/dist/mysql/mysqlDialect.js +13 -0
- package/dist/schema/canonicalType.d.ts +14 -2
- package/dist/schema/canonicalType.js +41 -31
- package/dist/schema/index.d.ts +1 -1
- package/dist/schema/schemaASTBuilder.d.ts +8 -1
- package/dist/schema/schemaASTBuilder.js +56 -47
- package/dist/schema/types.d.ts +10 -37
- package/dist/sqlite/abstractSqliteQuerier.d.ts +39 -0
- package/dist/sqlite/abstractSqliteQuerier.js +44 -0
- package/dist/sqlite/bunSqliteAdapter.bun.d.ts +26 -0
- package/dist/sqlite/bunSqliteAdapter.bun.js +25 -0
- package/dist/sqlite/hranaQuerier.d.ts +54 -0
- package/dist/sqlite/hranaQuerier.js +90 -0
- package/dist/sqlite/hranaQuerierPool.d.ts +21 -0
- package/dist/sqlite/hranaQuerierPool.js +25 -0
- package/dist/sqlite/index.d.ts +2 -1
- package/dist/sqlite/index.js +2 -1
- package/dist/sqlite/sqliteDialect.d.ts +18 -4
- package/dist/sqlite/sqliteDialect.js +24 -24
- package/dist/sqlite/sqliteQuerier.d.ts +16 -9
- package/dist/sqlite/sqliteQuerier.js +4 -27
- package/dist/sqlite/sqliteQuerierPool.d.ts +14 -4
- package/dist/sqlite/sqliteQuerierPool.js +16 -5
- package/dist/turso/index.d.ts +3 -0
- package/dist/turso/index.js +3 -0
- package/dist/turso/local.d.ts +3 -0
- package/dist/turso/local.js +3 -0
- package/dist/turso/tursoDialect.d.ts +15 -0
- package/dist/turso/tursoDialect.js +18 -0
- package/dist/turso/tursoLocalQuerier.d.ts +25 -0
- package/dist/turso/tursoLocalQuerier.js +20 -0
- package/dist/turso/tursoLocalQuerierPool.d.ts +32 -0
- package/dist/turso/tursoLocalQuerierPool.js +39 -0
- package/dist/turso/tursoQuerier.d.ts +10 -0
- package/dist/turso/tursoQuerier.js +10 -0
- package/dist/turso/tursoQuerierPool.d.ts +39 -0
- package/dist/turso/tursoQuerierPool.js +38 -0
- package/dist/type/config.d.ts +0 -6
- package/dist/type/dialect.d.ts +12 -4
- package/dist/type/dialect.js +7 -1
- package/dist/type/entity.d.ts +66 -5
- package/dist/type/migration.d.ts +32 -23
- package/dist/type/vector.d.ts +5 -2
- package/dist/util/index.d.ts +1 -0
- package/dist/util/index.js +1 -0
- package/dist/util/indexColumn.util.d.ts +6 -0
- package/dist/util/indexColumn.util.js +26 -0
- package/package.json +16 -3
- package/dist/migrate/codegen/entityMerger.d.ts +0 -114
- package/dist/migrate/codegen/entityMerger.js +0 -293
- package/dist/migrate/codegen/migrationCodeGenerator.d.ts +0 -61
- package/dist/migrate/codegen/migrationCodeGenerator.js +0 -355
- package/dist/migrate/generator/index.d.ts +0 -2
- package/dist/migrate/generator/index.js +0 -2
- package/dist/migrate/sync/index.d.ts +0 -6
- package/dist/migrate/sync/index.js +0 -6
- package/dist/migrate/sync/schemaSync.d.ts +0 -131
- package/dist/migrate/sync/schemaSync.js +0 -259
- package/dist/sqlite/betterSqlite3Dialect.d.ts +0 -9
- package/dist/sqlite/betterSqlite3Dialect.js +0 -9
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
<h3>The smartest TypeScript ORM</h3>
|
|
11
11
|
|
|
12
|
-
<p>Type-safe to the leaf, serializable queries, no codegen, <a href="https://uql-orm.dev/benchmark">extremely fast</a>, and
|
|
12
|
+
<p>Type-safe to the leaf, serializable queries, no codegen, <a href="https://uql-orm.dev/benchmark">extremely fast</a>, and unified API across Postgres, CockroachDB, MySQL, SQLite, MongoDB, MariaDB, and the edge.</p>
|
|
13
13
|
|
|
14
14
|
<p>
|
|
15
15
|
<a href="https://uql-orm.dev"><b>Website</b></a> ·
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
---
|
|
30
30
|
|
|
31
31
|
```sh
|
|
32
|
-
npm install uql-orm pg # or mysql2, mariadb, better-sqlite3, mongodb, @libsql/client
|
|
32
|
+
npm install uql-orm pg # or mysql2, mariadb, better-sqlite3, mongodb, @tursodatabase/serverless, @libsql/client
|
|
33
33
|
```
|
|
34
34
|
|
|
35
35
|
Decorators also need `reflect-metadata` ([setup](https://uql-orm.dev/getting-started)); the
|
|
@@ -49,12 +49,13 @@ from the browser to the server. The same object runs on every supported database
|
|
|
49
49
|
|
|
50
50
|
## Why UQL?
|
|
51
51
|
|
|
52
|
-
- **The fastest.** Wins [all 8 categories](https://uql-orm.dev/benchmark) of our [open benchmark](https://github.com/rogerpadilla/ts-orm-benchmark), beating even query builders like Knex and Kysely: ~2.
|
|
52
|
+
- **The fastest.** Wins [all 8 categories](https://uql-orm.dev/benchmark) of our [open benchmark](https://github.com/rogerpadilla/ts-orm-benchmark), beating even query builders like Knex and Kysely: ~2.3× faster than the runner-up on average, close to 4M ops/s on simple SELECTs.
|
|
53
53
|
- **Light.** Zero dependencies, under 1 MB installed, every dialect included.
|
|
54
54
|
- **Queries are data, not method chains.** Plain JSON in, typed rows out. There's no DSL to learn and nothing to compile.
|
|
55
55
|
- **Type-safe to the leaf.** Operators are gated per field type, and JSON/JSONB dot-paths resolve each path's value type, so `{ age: { $like: 'x' } }` or a typo'd path is a compile error instead of a runtime surprise.
|
|
56
56
|
- **No codegen.** Entities are TypeScript classes, so your code *is* the schema. No `.prisma` file to regenerate, no generated client to keep in sync.
|
|
57
|
-
- **One API everywhere.** PostgreSQL, CockroachDB, MySQL, MariaDB, SQLite,
|
|
57
|
+
- **One API everywhere.** PostgreSQL, CockroachDB, MySQL, MariaDB, SQLite, Turso, LibSQL, Neon, Cloudflare D1, Bun SQL, and MongoDB.
|
|
58
|
+
- **First ORM with a native Turso driver.** Turso Cloud over pure `fetch()` with zero native dependencies, so it runs on Cloudflare Workers and Vercel Edge, plus the embedded Rust engine for local-first apps.
|
|
58
59
|
- **The hard things are built in.** [Semantic and vector search](https://uql-orm.dev/ai-semantic-search), [non-bypassable multi-tenant filters](https://uql-orm.dev/multi-tenancy), [entity-first migrations](https://uql-orm.dev/migrations), [soft-delete with restore](https://uql-orm.dev/entities/soft-delete), [streaming](https://uql-orm.dev/querying/streaming), and [a REST API from your entities](https://uql-orm.dev/extensions-http).
|
|
59
60
|
|
|
60
61
|
## Get started
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { CockroachDialect } from '../cockroachdb/cockroachDialect.js';
|
|
2
|
-
import type {
|
|
2
|
+
import type { DialectFeatures } from '../type/index.js';
|
|
3
3
|
/**
|
|
4
4
|
* CockroachDB Dialect specialization for the `bun:sql` driver, which routes CockroachDB
|
|
5
5
|
* connections through its own Postgres wire-protocol implementation (see
|
|
@@ -8,5 +8,5 @@ import type { DialectOptions } from '../dialect/abstractDialect.js';
|
|
|
8
8
|
* (verified directly against a live CockroachDB instance via `bun:sql`).
|
|
9
9
|
*/
|
|
10
10
|
export declare class BunSqlCockroachDialect extends CockroachDialect {
|
|
11
|
-
|
|
11
|
+
protected readonly featureOverrides: Partial<DialectFeatures>;
|
|
12
12
|
}
|
|
@@ -8,14 +8,8 @@ import { POSTGRES_WIRE_DRIVER_CAPABILITIES } from '../postgres/postgresWireDrive
|
|
|
8
8
|
* (verified directly against a live CockroachDB instance via `bun:sql`).
|
|
9
9
|
*/
|
|
10
10
|
export class BunSqlCockroachDialect extends CockroachDialect {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
...POSTGRES_WIRE_DRIVER_CAPABILITIES,
|
|
16
|
-
explicitJsonCast: true,
|
|
17
|
-
...options.driverCapabilities,
|
|
18
|
-
},
|
|
19
|
-
});
|
|
20
|
-
}
|
|
11
|
+
featureOverrides = {
|
|
12
|
+
...POSTGRES_WIRE_DRIVER_CAPABILITIES,
|
|
13
|
+
explicitJsonCast: true,
|
|
14
|
+
};
|
|
21
15
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { DialectOptions } from '../dialect/abstractDialect.js';
|
|
2
1
|
import { PostgresDialect } from '../postgres/postgresDialect.js';
|
|
2
|
+
import type { DialectFeatures } from '../type/index.js';
|
|
3
3
|
/**
|
|
4
4
|
* Postgres Dialect specialization for the `bun:sql` driver.
|
|
5
5
|
*
|
|
@@ -7,5 +7,5 @@ import { PostgresDialect } from '../postgres/postgresDialect.js';
|
|
|
7
7
|
* reliably; `PgDialect` omits the text re-cast.
|
|
8
8
|
*/
|
|
9
9
|
export declare class BunSqlPostgresDialect extends PostgresDialect {
|
|
10
|
-
|
|
10
|
+
protected readonly featureOverrides: Partial<DialectFeatures>;
|
|
11
11
|
}
|
|
@@ -7,14 +7,8 @@ import { POSTGRES_WIRE_DRIVER_CAPABILITIES } from '../postgres/postgresWireDrive
|
|
|
7
7
|
* reliably; `PgDialect` omits the text re-cast.
|
|
8
8
|
*/
|
|
9
9
|
export class BunSqlPostgresDialect extends PostgresDialect {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
...POSTGRES_WIRE_DRIVER_CAPABILITIES,
|
|
15
|
-
explicitJsonCast: true,
|
|
16
|
-
...options.driverCapabilities,
|
|
17
|
-
},
|
|
18
|
-
});
|
|
19
|
-
}
|
|
10
|
+
featureOverrides = {
|
|
11
|
+
...POSTGRES_WIRE_DRIVER_CAPABILITIES,
|
|
12
|
+
explicitJsonCast: true,
|
|
13
|
+
};
|
|
20
14
|
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import type { DialectOptions } from '../dialect/abstractDialect.js';
|
|
2
1
|
import { PgLikeSqlDialect } from '../dialect/pgLikeSqlDialect.js';
|
|
3
|
-
import type { VectorDistance } from '../type/index.js';
|
|
2
|
+
import type { IndexFeature, IndexSchema, VectorDistance } from '../type/index.js';
|
|
4
3
|
/**
|
|
5
4
|
* CockroachDB Dialect.
|
|
6
5
|
* Shares AST/quoting/JSONB/full-text-search/vector-search/upsert logic with Postgres via
|
|
@@ -14,6 +13,23 @@ import type { VectorDistance } from '../type/index.js';
|
|
|
14
13
|
*/
|
|
15
14
|
export declare class CockroachDialect extends PgLikeSqlDialect {
|
|
16
15
|
readonly dialectName = "cockroachdb";
|
|
17
|
-
readonly
|
|
18
|
-
|
|
16
|
+
readonly vectorMetrics: ReadonlyMap<VectorDistance, {
|
|
17
|
+
op: string;
|
|
18
|
+
opsSuffix: string;
|
|
19
|
+
}>;
|
|
20
|
+
/**
|
|
21
|
+
* `NULLS FIRST/LAST` answers "unimplemented: this syntax" and `jsonb_path_ops` "operator class is
|
|
22
|
+
* not supported" (both verified on v26.2), so neither is offered here.
|
|
23
|
+
*/
|
|
24
|
+
protected readonly indexFeatures: Set<IndexFeature>;
|
|
25
|
+
/**
|
|
26
|
+
* CockroachDB's vector index is native and has its own syntax: `CREATE VECTOR INDEX ... ("col"
|
|
27
|
+
* vector_cosine_ops)`, with no access-method keyword, and tuning knobs of its own names that UQL
|
|
28
|
+
* does not map. `type: 'vector'` is its trigger, the same generic value MariaDB's inline index uses.
|
|
29
|
+
*/
|
|
30
|
+
private isNativeVectorIndex;
|
|
31
|
+
protected isVectorIndex(index: IndexSchema): boolean;
|
|
32
|
+
protected indexKeyword(index: IndexSchema): string;
|
|
33
|
+
protected indexAccessMethod(index: IndexSchema): string;
|
|
34
|
+
protected indexTuning(index: IndexSchema): string;
|
|
19
35
|
}
|
|
@@ -12,24 +12,39 @@ import { PgLikeSqlDialect } from '../dialect/pgLikeSqlDialect.js';
|
|
|
12
12
|
*/
|
|
13
13
|
export class CockroachDialect extends PgLikeSqlDialect {
|
|
14
14
|
dialectName = 'cockroachdb';
|
|
15
|
-
// CockroachDB
|
|
16
|
-
//
|
|
17
|
-
//
|
|
18
|
-
//
|
|
19
|
-
//
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
['
|
|
23
|
-
['
|
|
24
|
-
['inner', 'vector_ip_ops'],
|
|
15
|
+
// CockroachDB implements 3 of pgvector's 4 metrics: `<+>` and `vector_l1_ops` throw
|
|
16
|
+
// "unimplemented: operator class ... is not supported" (verified live on v26.2), which its own docs
|
|
17
|
+
// list under "Known limitations": https://www.cockroachlabs.com/docs/stable/vector-indexes -
|
|
18
|
+
// tracked upstream at https://github.com/cockroachdb/cockroach/issues/147839. Re-check that issue
|
|
19
|
+
// before adding `l1` here; it is omitted on purpose, not an oversight.
|
|
20
|
+
vectorMetrics = new Map([
|
|
21
|
+
['cosine', { op: '<=>', opsSuffix: 'cosine' }],
|
|
22
|
+
['l2', { op: '<->', opsSuffix: 'l2' }],
|
|
23
|
+
['inner', { op: '<#>', opsSuffix: 'ip' }],
|
|
25
24
|
]);
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
25
|
+
/**
|
|
26
|
+
* `NULLS FIRST/LAST` answers "unimplemented: this syntax" and `jsonb_path_ops` "operator class is
|
|
27
|
+
* not supported" (both verified on v26.2), so neither is offered here.
|
|
28
|
+
*/
|
|
29
|
+
indexFeatures = new Set(['expression', 'include']);
|
|
30
|
+
/**
|
|
31
|
+
* CockroachDB's vector index is native and has its own syntax: `CREATE VECTOR INDEX ... ("col"
|
|
32
|
+
* vector_cosine_ops)`, with no access-method keyword, and tuning knobs of its own names that UQL
|
|
33
|
+
* does not map. `type: 'vector'` is its trigger, the same generic value MariaDB's inline index uses.
|
|
34
|
+
*/
|
|
35
|
+
isNativeVectorIndex(index) {
|
|
36
|
+
return index.type === 'vector';
|
|
37
|
+
}
|
|
38
|
+
isVectorIndex(index) {
|
|
39
|
+
return this.isNativeVectorIndex(index) || super.isVectorIndex(index);
|
|
40
|
+
}
|
|
41
|
+
indexKeyword(index) {
|
|
42
|
+
return this.isNativeVectorIndex(index) ? 'VECTOR INDEX' : super.indexKeyword(index);
|
|
43
|
+
}
|
|
44
|
+
indexAccessMethod(index) {
|
|
45
|
+
return this.isNativeVectorIndex(index) ? '' : super.indexAccessMethod(index);
|
|
46
|
+
}
|
|
47
|
+
indexTuning(index) {
|
|
48
|
+
return this.isNativeVectorIndex(index) ? '' : super.indexTuning(index);
|
|
34
49
|
}
|
|
35
50
|
}
|
package/dist/d1/d1Querier.d.ts
CHANGED
|
@@ -35,11 +35,12 @@ export interface D1Database {
|
|
|
35
35
|
batch<T = unknown>(statements: D1PreparedStatement[]): Promise<D1Result<T>[]>;
|
|
36
36
|
exec(query: string): Promise<D1ExecResult>;
|
|
37
37
|
}
|
|
38
|
+
/** The only part of a D1 binding the querier uses; a full {@link D1Database} satisfies it. */
|
|
39
|
+
export type D1Preparer = Pick<D1Database, 'prepare'>;
|
|
38
40
|
export declare class D1Querier extends AbstractSqliteQuerier {
|
|
39
|
-
readonly db:
|
|
41
|
+
readonly db: D1Preparer;
|
|
40
42
|
readonly extra?: ExtraOptions | undefined;
|
|
41
|
-
constructor(db:
|
|
43
|
+
constructor(db: D1Preparer, dialect: SqliteDialect, extra?: ExtraOptions | undefined);
|
|
42
44
|
internalAll<T>(query: string, values?: unknown[]): Promise<T[]>;
|
|
43
45
|
internalRun(query: string, values?: unknown[]): Promise<import("../type/query.js").QueryUpdateResult>;
|
|
44
|
-
internalRelease(): Promise<void>;
|
|
45
46
|
}
|
package/dist/d1/d1Querier.js
CHANGED
|
@@ -6,4 +6,11 @@ import { SqliteDialect } from '../sqlite/sqliteDialect.js';
|
|
|
6
6
|
*/
|
|
7
7
|
export declare class D1SqliteDialect extends SqliteDialect {
|
|
8
8
|
readonly maxBindValues: number;
|
|
9
|
+
/**
|
|
10
|
+
* D1 loads no extensions (its allowlist is FTS5, JSON and the math functions) and has no vector
|
|
11
|
+
* functions of its own, so the sqlite-vec names inherited from {@link SqliteDialect} would compile
|
|
12
|
+
* to SQL that only fails once it reaches the edge. `raw()` is no escape hatch either, hence a
|
|
13
|
+
* message that names the product that does the job.
|
|
14
|
+
*/
|
|
15
|
+
protected appendVectorSort(): never;
|
|
9
16
|
}
|
|
@@ -7,4 +7,13 @@ import { SqliteDialect } from '../sqlite/sqliteDialect.js';
|
|
|
7
7
|
export class D1SqliteDialect extends SqliteDialect {
|
|
8
8
|
// Cloudflare D1 caps bound parameters at 100 per query.
|
|
9
9
|
maxBindValues = 100;
|
|
10
|
+
/**
|
|
11
|
+
* D1 loads no extensions (its allowlist is FTS5, JSON and the math functions) and has no vector
|
|
12
|
+
* functions of its own, so the sqlite-vec names inherited from {@link SqliteDialect} would compile
|
|
13
|
+
* to SQL that only fails once it reaches the edge. `raw()` is no escape hatch either, hence a
|
|
14
|
+
* message that names the product that does the job.
|
|
15
|
+
*/
|
|
16
|
+
appendVectorSort() {
|
|
17
|
+
throw new TypeError('Cloudflare D1 has no vector functions and cannot load sqlite-vec. Use Cloudflare Vectorize for vector search.');
|
|
18
|
+
}
|
|
10
19
|
}
|
|
@@ -20,12 +20,17 @@ export declare abstract class AbstractDialect {
|
|
|
20
20
|
* {@link DialectOptions.driverCapabilities} overrides. Each concrete dialect declares its own.
|
|
21
21
|
*/
|
|
22
22
|
protected abstract readonly featureDefaults: DialectFeatures;
|
|
23
|
+
/**
|
|
24
|
+
* How this dialect differs from the family it extends, so a subclass states only its deltas rather
|
|
25
|
+
* than repeating {@link featureDefaults} in full or injecting them through its constructor.
|
|
26
|
+
*/
|
|
27
|
+
protected readonly featureOverrides: Partial<DialectFeatures>;
|
|
23
28
|
readonly namingStrategy: NamingStrategy | undefined;
|
|
24
29
|
constructor(options?: DialectOptions);
|
|
25
30
|
/**
|
|
26
|
-
* Effective features: {@link featureDefaults}
|
|
27
|
-
* Computed lazily (and memoized)
|
|
28
|
-
* after `super()` returns.
|
|
31
|
+
* Effective features: {@link featureDefaults}, then this dialect's {@link featureOverrides}, then
|
|
32
|
+
* any per-instance {@link DialectOptions.driverCapabilities}. Computed lazily (and memoized)
|
|
33
|
+
* because both are subclass fields, initialized only after `super()` returns.
|
|
29
34
|
*/
|
|
30
35
|
get features(): DialectFeatures;
|
|
31
36
|
/**
|
|
@@ -4,6 +4,11 @@ import { applyFilters, buildQueryWhereAsMap } from '../util/dialect.util.js';
|
|
|
4
4
|
*/
|
|
5
5
|
export class AbstractDialect {
|
|
6
6
|
options;
|
|
7
|
+
/**
|
|
8
|
+
* How this dialect differs from the family it extends, so a subclass states only its deltas rather
|
|
9
|
+
* than repeating {@link featureDefaults} in full or injecting them through its constructor.
|
|
10
|
+
*/
|
|
11
|
+
featureOverrides = {};
|
|
7
12
|
namingStrategy;
|
|
8
13
|
#features;
|
|
9
14
|
constructor(options = {}) {
|
|
@@ -11,12 +16,12 @@ export class AbstractDialect {
|
|
|
11
16
|
this.namingStrategy = options.namingStrategy;
|
|
12
17
|
}
|
|
13
18
|
/**
|
|
14
|
-
* Effective features: {@link featureDefaults}
|
|
15
|
-
* Computed lazily (and memoized)
|
|
16
|
-
* after `super()` returns.
|
|
19
|
+
* Effective features: {@link featureDefaults}, then this dialect's {@link featureOverrides}, then
|
|
20
|
+
* any per-instance {@link DialectOptions.driverCapabilities}. Computed lazily (and memoized)
|
|
21
|
+
* because both are subclass fields, initialized only after `super()` returns.
|
|
17
22
|
*/
|
|
18
23
|
get features() {
|
|
19
|
-
this.#features ??= { ...this.featureDefaults, ...this.options.driverCapabilities };
|
|
24
|
+
this.#features ??= { ...this.featureDefaults, ...this.featureOverrides, ...this.options.driverCapabilities };
|
|
20
25
|
return this.#features;
|
|
21
26
|
}
|
|
22
27
|
/**
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import { type EntityMeta, type FieldKey, type FieldOptions, type IsolationLevel, type JsonColumnType, type JsonUpdateOp, type Query, type QueryAggMap, type QueryAggregate, type QueryComparisonOptions, type QueryConflictPaths, type QueryContext, type QueryDialect, type QueryExclude, type QueryGroupMap, type QueryHavingMap, type QueryOptions, type QueryPager, type QueryPopulate, QueryRaw, type QueryRawFnOptions, type QuerySearch, type QuerySelect, type QuerySelectOptions, type QuerySelectValue, type QuerySizeComparisonOps, type QuerySortMap, type QueryWhere, type QueryWhereArray, type QueryWhereFieldOperatorMap, type QueryWhereMap, type QueryWhereOptions, type RelationOptions, type SqlDialectName, type SqlQueryDialect, type Type, type UpdatePayload } from '../type/index.js';
|
|
2
|
-
import {
|
|
3
|
-
|
|
1
|
+
import { type EntityMeta, type FieldKey, type FieldOptions, type IsolationLevel, type JsonColumnType, type JsonUpdateOp, type Query, type QueryAggMap, type QueryAggregate, type QueryComparisonOptions, type QueryConflictPaths, type QueryContext, type QueryDialect, type QueryExclude, type QueryGroupMap, type QueryHavingMap, type QueryOptions, type QueryPager, type QueryPopulate, QueryRaw, type QueryRawFnOptions, type QuerySearch, type QuerySelect, type QuerySelectOptions, type QuerySelectValue, type QuerySizeComparisonOps, type QuerySortMap, type QueryTextSearchOptions, type QueryWhere, type QueryWhereArray, type QueryWhereFieldOperatorMap, type QueryWhereMap, type QueryWhereOptions, type RelationOptions, type SqlDialectName, type SqlQueryDialect, type Type, type UpdatePayload } from '../type/index.js';
|
|
2
|
+
import { IndexSqlDialect } from './indexSqlDialect.js';
|
|
3
|
+
/** How a column's values are bound: see {@link AbstractSqlDialect.persistKind}. */
|
|
4
|
+
type PersistKind = 'plain' | 'json' | 'vector';
|
|
5
|
+
export declare abstract class AbstractSqlDialect extends IndexSqlDialect implements QueryDialect, SqlQueryDialect {
|
|
4
6
|
abstract readonly dialectName: SqlDialectName;
|
|
5
7
|
abstract readonly escapeIdChar: '"' | '`';
|
|
6
8
|
abstract readonly serialPrimaryKey: string;
|
|
@@ -47,6 +49,18 @@ export declare abstract class AbstractSqlDialect extends VectorSqlDialect implem
|
|
|
47
49
|
returningId<E>(entity: Type<E>): string;
|
|
48
50
|
search<E>(ctx: QueryContext, entity: Type<E>, q?: Query<E>, opts?: QueryOptions): void;
|
|
49
51
|
selectFields<E>(ctx: QueryContext, entity: Type<E>, select: QuerySelectValue<E> | undefined, opts?: QuerySelectOptions, exclude?: QueryExclude<E>): void;
|
|
52
|
+
/**
|
|
53
|
+
* The expression a scalar field is read through, the plain column by default. MariaDB reads a
|
|
54
|
+
* vector column back with `VEC_ToText`, since selecting it raw yields its binary form.
|
|
55
|
+
*/
|
|
56
|
+
protected selectFieldExpr(escapedColumn: string, _field: FieldOptions): string;
|
|
57
|
+
/**
|
|
58
|
+
* The `$text` full-text predicate, which every engine spells differently: `MATCH ... AGAINST`
|
|
59
|
+
* (MySQL family), `to_tsvector @@ websearch_to_tsquery` (Postgres-wire), an FTS5 `MATCH` against
|
|
60
|
+
* the table itself (SQLite). No portable form exists, so a dialect without one says so here rather
|
|
61
|
+
* than inheriting another engine's syntax.
|
|
62
|
+
*/
|
|
63
|
+
protected appendTextSearch<E>(_ctx: QueryContext, _entity: Type<E>, _meta: EntityMeta<E>, _search: QueryTextSearchOptions<E>): void;
|
|
50
64
|
select<E>(ctx: QueryContext, entity: Type<E>, select: QuerySelectValue<E> | undefined, exclude?: QueryExclude<E>, populate?: QueryPopulate<E>, opts?: QueryOptions, distinct?: boolean, sort?: QuerySortMap<E>): void;
|
|
51
65
|
private resolveRelationAwarePrefix;
|
|
52
66
|
protected selectRelationFields<E>(ctx: QueryContext, entity: Type<E>, select: QuerySelect<E> | undefined, populate: QueryPopulate<E> | undefined, opts?: {
|
|
@@ -195,6 +209,11 @@ export declare abstract class AbstractSqlDialect extends VectorSqlDialect implem
|
|
|
195
209
|
protected havingCondition(ctx: QueryContext, expr: string, condition: QueryHavingMap[string]): void;
|
|
196
210
|
find<E>(ctx: QueryContext, entity: Type<E>, q?: Query<E>, opts?: QueryOptions): void;
|
|
197
211
|
insert<E>(ctx: QueryContext, entity: Type<E>, payload: E | E[], opts?: QueryOptions): void;
|
|
212
|
+
/**
|
|
213
|
+
* `INSERT INTO ... VALUES (...)` and nothing more. The upsert builders extend this rather than
|
|
214
|
+
* {@link insert}: their own clause has to come before the `RETURNING`, not after it.
|
|
215
|
+
*/
|
|
216
|
+
protected appendInsertValues<E>(ctx: QueryContext, entity: Type<E>, payload: E | E[], opts?: QueryOptions): void;
|
|
198
217
|
/**
|
|
199
218
|
* Emit the value for a column a payload record does not provide (the column list is the union
|
|
200
219
|
* across all records). `DEFAULT` delegates to the database default; SQLite overrides this since
|
|
@@ -208,13 +227,21 @@ export declare abstract class AbstractSqlDialect extends VectorSqlDialect implem
|
|
|
208
227
|
delete<E>(ctx: QueryContext, entity: Type<E>, q: QuerySearch<E>, opts?: QueryOptions): void;
|
|
209
228
|
escapeId(val: string, forbidQualified?: boolean, addDot?: boolean): string;
|
|
210
229
|
/**
|
|
211
|
-
*
|
|
212
|
-
* {@link appendVectorValue} rather than this, so the chain runs once per
|
|
213
|
-
* and delegating back to `super` ran every check twice, measurably slowing
|
|
230
|
+
* Bind one persisted value, classifying its column on the spot. Dialects override
|
|
231
|
+
* {@link appendJsonValue} and {@link appendVectorValue} rather than this, so the chain runs once per
|
|
232
|
+
* value - overriding this and delegating back to `super` ran every check twice, measurably slowing
|
|
233
|
+
* every INSERT/UPDATE.
|
|
214
234
|
*/
|
|
215
235
|
protected formatPersistableValue(ctx: QueryContext, field: FieldOptions | undefined, value: unknown): void;
|
|
236
|
+
/**
|
|
237
|
+
* How a column's values are written. A function of the column, not of the value, so a bulk insert
|
|
238
|
+
* classifies each column once instead of re-deciding per row: a 20-row, 6-column insert asked
|
|
239
|
+
* `isJsonType` and `isVectorFieldType` 120 times to get the same six answers.
|
|
240
|
+
*/
|
|
241
|
+
protected persistKind(field: FieldOptions | undefined): PersistKind;
|
|
242
|
+
/** The one type dispatch for a persisted value, over a column kind decided by the caller. */
|
|
243
|
+
private writePersistableValue;
|
|
216
244
|
protected appendJsonValue(ctx: QueryContext, value: unknown, _type: JsonColumnType): void;
|
|
217
|
-
protected appendVectorValue(ctx: QueryContext, value: readonly unknown[]): void;
|
|
218
245
|
/**
|
|
219
246
|
* Reads `operand` as a JSON value. Passing the `?` placeholder yields the cast for a bound
|
|
220
247
|
* parameter, and passing an expression re-reads text as JSON - the same SQL either way, which is
|
|
@@ -332,3 +359,4 @@ export declare abstract class AbstractSqlDialect extends VectorSqlDialect implem
|
|
|
332
359
|
protected numericCast(expr: string): string;
|
|
333
360
|
toString(): string;
|
|
334
361
|
}
|
|
362
|
+
export {};
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { getMeta } from '../entity/index.js';
|
|
2
2
|
import { QueryRaw, RAW_ALIAS, RAW_VALUE, } from '../type/index.js';
|
|
3
|
-
import { asSelectMap, buildQueryWhereAsMap, buildSortMap, escapeSqlId, fillOnFields, filterFieldKeys, flatObject,
|
|
3
|
+
import { asSelectMap, buildQueryWhereAsMap, buildSortMap, escapeSqlId, fillOnFields, filterFieldKeys, flatObject, getInsertFieldKeys, getKeys, getRelationRequestSummary, getSoftDeleteValue, hasKeys, hasMultipleKeys, isJsonType, isJsonUpdateOp, isOperatorObject, isOperatorOnlyObject, isPopulatingRelations, isVectorSearch, normalizeScalarFieldSelection, parseGroupMap, parseRelationAtKey, parseRelationSize, raw, someValue, withoutSoftDeleteFilter, } from '../util/index.js';
|
|
4
4
|
import { escapeAnsiSqlLiteral, escapeSingleQuotes } from '../util/sqlLiteral.js';
|
|
5
|
+
import { IndexSqlDialect } from './indexSqlDialect.js';
|
|
5
6
|
import { buildElemMatchConditions } from './jsonArrayElemMatchUtils.js';
|
|
6
7
|
import { JSON_ELEM_ALIAS_PREFIX, jsonElemExists } from './jsonSql.js';
|
|
7
8
|
import { SqlQueryContext } from './queryContext.js';
|
|
8
|
-
import {
|
|
9
|
-
export class AbstractSqlDialect extends
|
|
9
|
+
import { isVectorFieldType } from './vectorCast.js';
|
|
10
|
+
export class AbstractSqlDialect extends IndexSqlDialect {
|
|
10
11
|
isolationLevelStrategy = 'inline';
|
|
11
12
|
alterColumnStrategy = 'single-statement';
|
|
12
13
|
alterColumnSyntax = 'ALTER COLUMN';
|
|
@@ -135,7 +136,6 @@ export class AbstractSqlDialect extends VectorSqlDialect {
|
|
|
135
136
|
const field = meta.fields[key];
|
|
136
137
|
if (!field)
|
|
137
138
|
return;
|
|
138
|
-
const columnName = this.resolveColumnName(key, field);
|
|
139
139
|
if (field.virtual) {
|
|
140
140
|
this.getRawValue(ctx, {
|
|
141
141
|
value: raw(field.virtual[RAW_VALUE], key),
|
|
@@ -143,17 +143,35 @@ export class AbstractSqlDialect extends VectorSqlDialect {
|
|
|
143
143
|
escapedPrefix,
|
|
144
144
|
autoPrefixAlias: opts.autoPrefixAlias,
|
|
145
145
|
});
|
|
146
|
+
return;
|
|
146
147
|
}
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
148
|
+
const columnName = this.resolveColumnName(key, field);
|
|
149
|
+
const column = escapedPrefix + this.escapeId(columnName);
|
|
150
|
+
const expr = this.selectFieldExpr(column, field);
|
|
151
|
+
ctx.append(expr);
|
|
152
|
+
// An expression needs the alias too, or the row comes back keyed by the expression text.
|
|
153
|
+
if (expr !== column || columnName !== key || opts.autoPrefixAlias) {
|
|
154
|
+
ctx.append(' ' + this.escapeId(prefix + key, true));
|
|
153
155
|
}
|
|
154
156
|
}
|
|
155
157
|
});
|
|
156
158
|
}
|
|
159
|
+
/**
|
|
160
|
+
* The expression a scalar field is read through, the plain column by default. MariaDB reads a
|
|
161
|
+
* vector column back with `VEC_ToText`, since selecting it raw yields its binary form.
|
|
162
|
+
*/
|
|
163
|
+
selectFieldExpr(escapedColumn, _field) {
|
|
164
|
+
return escapedColumn;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* The `$text` full-text predicate, which every engine spells differently: `MATCH ... AGAINST`
|
|
168
|
+
* (MySQL family), `to_tsvector @@ websearch_to_tsquery` (Postgres-wire), an FTS5 `MATCH` against
|
|
169
|
+
* the table itself (SQLite). No portable form exists, so a dialect without one says so here rather
|
|
170
|
+
* than inheriting another engine's syntax.
|
|
171
|
+
*/
|
|
172
|
+
appendTextSearch(_ctx, _entity, _meta, _search) {
|
|
173
|
+
throw new TypeError(`${this.dialectName} does not support $text full-text search`);
|
|
174
|
+
}
|
|
157
175
|
select(ctx, entity, select, exclude, populate, opts = {}, distinct, sort) {
|
|
158
176
|
const meta = getMeta(entity);
|
|
159
177
|
const tableName = this.resolveTableName(entity, meta);
|
|
@@ -296,16 +314,7 @@ export class AbstractSqlDialect extends VectorSqlDialect {
|
|
|
296
314
|
return;
|
|
297
315
|
}
|
|
298
316
|
if (key === '$text') {
|
|
299
|
-
|
|
300
|
-
const searchFields = search.$fields ?? getFieldKeys(meta.fields);
|
|
301
|
-
const fields = searchFields.map((fKey) => {
|
|
302
|
-
const field = meta.fields[fKey];
|
|
303
|
-
const columnName = this.resolveColumnName(fKey, field);
|
|
304
|
-
return this.escapeId(columnName);
|
|
305
|
-
});
|
|
306
|
-
ctx.append(`MATCH(${fields.join(', ')}) AGAINST(`);
|
|
307
|
-
ctx.addValue(search.$value);
|
|
308
|
-
ctx.append(')');
|
|
317
|
+
this.appendTextSearch(ctx, entity, meta, val);
|
|
309
318
|
return;
|
|
310
319
|
}
|
|
311
320
|
if (key === '$and' || key === '$or' || key === '$not' || key === '$nor') {
|
|
@@ -911,6 +920,18 @@ export class AbstractSqlDialect extends VectorSqlDialect {
|
|
|
911
920
|
this.search(ctx, entity, q, opts);
|
|
912
921
|
}
|
|
913
922
|
insert(ctx, entity, payload, opts) {
|
|
923
|
+
this.appendInsertValues(ctx, entity, payload, opts);
|
|
924
|
+
// Every engine whose ids come back from the statement itself wants the same clause, so it is
|
|
925
|
+
// appended once here instead of in an identical `insert` override per dialect.
|
|
926
|
+
if (this.insertIdSource === 'returning') {
|
|
927
|
+
ctx.append(` ${this.returningId(entity)}`);
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
/**
|
|
931
|
+
* `INSERT INTO ... VALUES (...)` and nothing more. The upsert builders extend this rather than
|
|
932
|
+
* {@link insert}: their own clause has to come before the `RETURNING`, not after it.
|
|
933
|
+
*/
|
|
934
|
+
appendInsertValues(ctx, entity, payload, opts) {
|
|
914
935
|
const meta = getMeta(entity);
|
|
915
936
|
const payloads = fillOnFields(meta, payload, 'onInsert');
|
|
916
937
|
const keys = getInsertFieldKeys(meta, payloads);
|
|
@@ -919,10 +940,13 @@ export class AbstractSqlDialect extends VectorSqlDialect {
|
|
|
919
940
|
const width = keys.length;
|
|
920
941
|
const fields = new Array(width);
|
|
921
942
|
const columns = new Array(width);
|
|
943
|
+
const kinds = new Array(width);
|
|
922
944
|
for (let i = 0; i < width; i++) {
|
|
923
945
|
const key = keys[i];
|
|
924
|
-
|
|
946
|
+
const field = meta.fields[key];
|
|
947
|
+
fields[i] = field;
|
|
925
948
|
columns[i] = this.escapedColumnName(meta, key);
|
|
949
|
+
kinds[i] = this.persistKind(field);
|
|
926
950
|
}
|
|
927
951
|
const tableName = this.resolveTableName(entity, meta);
|
|
928
952
|
ctx.append(`INSERT INTO ${this.escapeId(tableName)} (${columns.join(', ')}) VALUES (`);
|
|
@@ -939,8 +963,12 @@ export class AbstractSqlDialect extends VectorSqlDialect {
|
|
|
939
963
|
if (value === undefined) {
|
|
940
964
|
this.appendDefaultInsertValue(ctx, fields[i]);
|
|
941
965
|
}
|
|
966
|
+
else if (kinds[i] === 'plain' && !(value instanceof QueryRaw)) {
|
|
967
|
+
// The overwhelmingly common case in a bulk insert, so it binds without a dispatch.
|
|
968
|
+
ctx.addValue(value);
|
|
969
|
+
}
|
|
942
970
|
else {
|
|
943
|
-
this.
|
|
971
|
+
this.writePersistableValue(ctx, kinds[i], fields[i], value);
|
|
944
972
|
}
|
|
945
973
|
}
|
|
946
974
|
}
|
|
@@ -983,13 +1011,13 @@ export class AbstractSqlDialect extends VectorSqlDialect {
|
|
|
983
1011
|
const updateCtx = this.createContext();
|
|
984
1012
|
const update = this.getUpsertUpdateAssignments(updateCtx, meta, conflictPaths, payload, (name) => `VALUES(${name})`);
|
|
985
1013
|
if (update) {
|
|
986
|
-
this.
|
|
1014
|
+
this.appendInsertValues(ctx, entity, payload);
|
|
987
1015
|
ctx.append(` ON DUPLICATE KEY UPDATE ${update}`);
|
|
988
1016
|
ctx.pushValue(...updateCtx.values);
|
|
989
1017
|
}
|
|
990
1018
|
else {
|
|
991
1019
|
const insertCtx = this.createContext();
|
|
992
|
-
this.
|
|
1020
|
+
this.appendInsertValues(insertCtx, entity, payload);
|
|
993
1021
|
ctx.append(insertCtx.sql.replace(/^INSERT/, 'INSERT IGNORE'));
|
|
994
1022
|
ctx.pushValue(...insertCtx.values);
|
|
995
1023
|
}
|
|
@@ -1045,22 +1073,38 @@ export class AbstractSqlDialect extends VectorSqlDialect {
|
|
|
1045
1073
|
return escapeSqlId(val, this.escapeIdChar, forbidQualified, addDot);
|
|
1046
1074
|
}
|
|
1047
1075
|
/**
|
|
1048
|
-
*
|
|
1049
|
-
* {@link appendVectorValue} rather than this, so the chain runs once per
|
|
1050
|
-
* and delegating back to `super` ran every check twice, measurably slowing
|
|
1076
|
+
* Bind one persisted value, classifying its column on the spot. Dialects override
|
|
1077
|
+
* {@link appendJsonValue} and {@link appendVectorValue} rather than this, so the chain runs once per
|
|
1078
|
+
* value - overriding this and delegating back to `super` ran every check twice, measurably slowing
|
|
1079
|
+
* every INSERT/UPDATE.
|
|
1051
1080
|
*/
|
|
1052
1081
|
formatPersistableValue(ctx, field, value) {
|
|
1082
|
+
this.writePersistableValue(ctx, this.persistKind(field), field, value);
|
|
1083
|
+
}
|
|
1084
|
+
/**
|
|
1085
|
+
* How a column's values are written. A function of the column, not of the value, so a bulk insert
|
|
1086
|
+
* classifies each column once instead of re-deciding per row: a 20-row, 6-column insert asked
|
|
1087
|
+
* `isJsonType` and `isVectorFieldType` 120 times to get the same six answers.
|
|
1088
|
+
*/
|
|
1089
|
+
persistKind(field) {
|
|
1090
|
+
const type = field?.type;
|
|
1091
|
+
if (isJsonType(type)) {
|
|
1092
|
+
return 'json';
|
|
1093
|
+
}
|
|
1094
|
+
return isVectorFieldType(type) ? 'vector' : 'plain';
|
|
1095
|
+
}
|
|
1096
|
+
/** The one type dispatch for a persisted value, over a column kind decided by the caller. */
|
|
1097
|
+
writePersistableValue(ctx, kind, field, value) {
|
|
1053
1098
|
if (value instanceof QueryRaw) {
|
|
1054
1099
|
this.getRawValue(ctx, { value });
|
|
1055
1100
|
return;
|
|
1056
1101
|
}
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
this.appendJsonValue(ctx, value, type);
|
|
1102
|
+
if (kind === 'json') {
|
|
1103
|
+
this.appendJsonValue(ctx, value, field?.type);
|
|
1060
1104
|
return;
|
|
1061
1105
|
}
|
|
1062
|
-
if (
|
|
1063
|
-
this.appendVectorValue(ctx, value);
|
|
1106
|
+
if (kind === 'vector' && Array.isArray(value)) {
|
|
1107
|
+
this.appendVectorValue(ctx, value, field);
|
|
1064
1108
|
return;
|
|
1065
1109
|
}
|
|
1066
1110
|
ctx.addValue(value);
|
|
@@ -1068,9 +1112,6 @@ export class AbstractSqlDialect extends VectorSqlDialect {
|
|
|
1068
1112
|
appendJsonValue(ctx, value, _type) {
|
|
1069
1113
|
ctx.addValue(value == null ? null : JSON.stringify(value));
|
|
1070
1114
|
}
|
|
1071
|
-
appendVectorValue(ctx, value) {
|
|
1072
|
-
ctx.addValue(`[${value.join(',')}]`);
|
|
1073
|
-
}
|
|
1074
1115
|
/**
|
|
1075
1116
|
* Reads `operand` as a JSON value. Passing the `?` placeholder yields the cast for a bound
|
|
1076
1117
|
* parameter, and passing an expression re-reads text as JSON - the same SQL either way, which is
|
package/dist/dialect/index.d.ts
CHANGED
|
@@ -4,5 +4,6 @@ export { PostgresDialect } from '../postgres/postgresDialect.js';
|
|
|
4
4
|
export { SqliteDialect } from '../sqlite/sqliteDialect.js';
|
|
5
5
|
export * from './abstractDialect.js';
|
|
6
6
|
export * from './abstractSqlDialect.js';
|
|
7
|
+
export * from './indexSqlDialect.js';
|
|
7
8
|
export * from './mysqlLikeSqlDialect.js';
|
|
8
9
|
export * from './queryContext.js';
|
package/dist/dialect/index.js
CHANGED
|
@@ -4,5 +4,6 @@ export { PostgresDialect } from '../postgres/postgresDialect.js';
|
|
|
4
4
|
export { SqliteDialect } from '../sqlite/sqliteDialect.js';
|
|
5
5
|
export * from './abstractDialect.js';
|
|
6
6
|
export * from './abstractSqlDialect.js';
|
|
7
|
+
export * from './indexSqlDialect.js';
|
|
7
8
|
export * from './mysqlLikeSqlDialect.js';
|
|
8
9
|
export * from './queryContext.js';
|