uql-orm 0.69.0 → 0.71.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.
Files changed (96) hide show
  1. package/README.md +2 -0
  2. package/dist/browser/querier/httpQuerier.d.ts +7 -7
  3. package/dist/browser/type/clientQuerier.d.ts +5 -5
  4. package/dist/browser/uql-browser.min.js +2 -2
  5. package/dist/browser/uql-browser.min.js.map +4 -4
  6. package/dist/cockroachdb/cockroachDialect.d.ts +6 -0
  7. package/dist/cockroachdb/cockroachDialect.js +10 -2
  8. package/dist/d1/d1SqliteDialect.d.ts +3 -0
  9. package/dist/d1/d1SqliteDialect.js +3 -1
  10. package/dist/dialect/abstractDialect.d.ts +8 -2
  11. package/dist/dialect/abstractDialect.js +17 -1
  12. package/dist/dialect/abstractSqlDialect.d.ts +21 -5
  13. package/dist/dialect/abstractSqlDialect.js +91 -46
  14. package/dist/dialect/aliases.d.ts +10 -7
  15. package/dist/dialect/aliases.js +10 -7
  16. package/dist/dialect/hydrateColumn.d.ts +3 -2
  17. package/dist/dialect/hydrateColumn.js +10 -1
  18. package/dist/dialect/mysqlLikeSqlDialect.js +5 -3
  19. package/dist/dialect/pgLikeSqlDialect.d.ts +17 -5
  20. package/dist/dialect/pgLikeSqlDialect.js +34 -15
  21. package/dist/dialect/queryJoins.d.ts +19 -1
  22. package/dist/dialect/queryJoins.js +54 -11
  23. package/dist/dialect/vectorCast.d.ts +2 -0
  24. package/dist/dialect/vectorCast.js +7 -0
  25. package/dist/dialect/vectorSqlDialect.d.ts +7 -3
  26. package/dist/dialect/vectorSqlDialect.js +15 -10
  27. package/dist/entity/decorator/members.d.ts +25 -11
  28. package/dist/entity/metadata/definition.d.ts +8 -3
  29. package/dist/libsql/libsqlDialect.d.ts +1 -1
  30. package/dist/libsql/libsqlDialect.js +3 -3
  31. package/dist/maria/mariaDialect.d.ts +3 -9
  32. package/dist/maria/mariaDialect.js +4 -13
  33. package/dist/maria/mariadbQuerier.js +9 -3
  34. package/dist/migrate/codegen/entityCodeGenerator.js +4 -2
  35. package/dist/migrate/ddl/index.d.ts +1 -0
  36. package/dist/migrate/ddl/index.js +4 -2
  37. package/dist/migrate/ddl/indexDdl.d.ts +2 -0
  38. package/dist/migrate/ddl/indexDdl.js +10 -2
  39. package/dist/migrate/ddl/pgIndexDdl.d.ts +3 -4
  40. package/dist/migrate/ddl/pgIndexDdl.js +11 -11
  41. package/dist/migrate/ddl/sqliteIndexDdl.d.ts +11 -0
  42. package/dist/migrate/ddl/sqliteIndexDdl.js +38 -0
  43. package/dist/migrate/generator/mongoCommand.d.ts +28 -0
  44. package/dist/migrate/generator/mongoCommand.js +8 -0
  45. package/dist/migrate/generator/mongoSchemaGenerator.d.ts +2 -0
  46. package/dist/migrate/generator/mongoSchemaGenerator.js +50 -6
  47. package/dist/migrate/introspection/mongoIntrospector.js +33 -7
  48. package/dist/migrate/introspection/postgresIntrospector.js +19 -0
  49. package/dist/migrate/introspection/sqliteIntrospector.d.ts +6 -0
  50. package/dist/migrate/introspection/sqliteIntrospector.js +29 -3
  51. package/dist/migrate/migrator.d.ts +2 -1
  52. package/dist/migrate/migrator.js +5 -3
  53. package/dist/mongo/mongoDialect.d.ts +33 -27
  54. package/dist/mongo/mongoDialect.js +178 -114
  55. package/dist/mongo/mongodbQuerier.d.ts +0 -2
  56. package/dist/mongo/mongodbQuerier.js +14 -13
  57. package/dist/mssql/mssqlDialect.js +4 -2
  58. package/dist/postgres/postgresDialect.js +2 -2
  59. package/dist/querier/abstractQuerier.d.ts +16 -11
  60. package/dist/querier/abstractQuerier.js +28 -8
  61. package/dist/querier/abstractQuerierPool.d.ts +9 -9
  62. package/dist/querier/abstractSqlQuerier.d.ts +1 -1
  63. package/dist/querier/abstractSqlQuerier.js +3 -3
  64. package/dist/schema/canonicalType.js +10 -4
  65. package/dist/schema/indexDifferences.d.ts +5 -2
  66. package/dist/schema/indexDifferences.js +5 -0
  67. package/dist/schema/schemaASTBuilder.js +3 -2
  68. package/dist/sqlite/localSqliteQuerierPool.d.ts +10 -11
  69. package/dist/sqlite/localSqliteQuerierPool.js +8 -11
  70. package/dist/sqlite/nodeSqliteQuerierPool.d.ts +4 -2
  71. package/dist/sqlite/nodeSqliteQuerierPool.js +7 -4
  72. package/dist/sqlite/sqliteDialect.d.ts +9 -1
  73. package/dist/sqlite/sqliteDialect.js +43 -3
  74. package/dist/sqlite/sqliteQuerierPool.d.ts +6 -5
  75. package/dist/sqlite/sqliteQuerierPool.js +10 -7
  76. package/dist/turso/tursoDialect.d.ts +1 -1
  77. package/dist/turso/tursoDialect.js +6 -2
  78. package/dist/turso/tursoLocalDialect.d.ts +1 -1
  79. package/dist/turso/tursoLocalDialect.js +1 -1
  80. package/dist/turso/tursoLocalQuerierPool.d.ts +4 -5
  81. package/dist/turso/tursoLocalQuerierPool.js +3 -10
  82. package/dist/type/dialect.d.ts +11 -0
  83. package/dist/type/entity.d.ts +45 -5
  84. package/dist/type/migration.d.ts +14 -9
  85. package/dist/type/query.d.ts +6 -0
  86. package/dist/type/queryAggregate.d.ts +73 -42
  87. package/dist/type/queryAggregate.js +4 -21
  88. package/dist/type/universalQuerier.d.ts +9 -9
  89. package/dist/type/vector.d.ts +17 -0
  90. package/dist/type/vector.js +6 -0
  91. package/dist/util/ddlExpression.util.d.ts +2 -0
  92. package/dist/util/ddlExpression.util.js +5 -0
  93. package/dist/util/dialect.util.d.ts +17 -3
  94. package/dist/util/dialect.util.js +40 -6
  95. package/package.json +5 -3
  96. package/skills/uql-orm/SKILL.md +142 -0
@@ -1,5 +1,5 @@
1
1
  import { assertSoleId, getMeta, idOf, namesKey, relationOf } from '../entity/index.js';
2
- import { cascadesOnDelete, childrenOf, clone, entityName, fillOnFields, filterFieldKeys, filterPersistableRelationKeys, forEachRequestedRelation, getKeys, getRelationRequestSummary, idOnlyQuery, isPagedQuery, isScalarId, LoggerWrapper, parentJoins, queryLoggerFor, parseRelationAtKey, parseRelationQueryValue, rowKey, runHooks, someKey, targetKeyColumns, whereIds, withoutSoftDeleteFilter, } from '../util/index.js';
2
+ import { cascadesOnDelete, childrenOf, clone, entityName, fillOnFields, filterFieldKeys, filterPersistableRelationKeys, forEachRequestedRelation, getKeys, getRelationRequestSummary, idOnlyQuery, isPagedQuery, hasKeys, isScalarId, LoggerWrapper, parentJoins, queryLoggerFor, parseRelationAtKey, parseRelationQueryValue, rowKey, runHooks, someKey, targetKeyColumns, whereIds, withoutSoftDeleteFilter, } from '../util/index.js';
3
3
  import { enrichError } from './queryError.js';
4
4
  /**
5
5
  * Refuses a nullish id, which would reduce to no filter at all, and a composite id missing a column,
@@ -27,6 +27,17 @@ function assertIdValue(entity, id) {
27
27
  function soleParentColumn(relOpts) {
28
28
  return parentJoins(relOpts, 1)[0].joined;
29
29
  }
30
+ /**
31
+ * A bulk write names the rows it changes: a `$where`, or a `$limit` capping how many it reaches. The
32
+ * caller's own clauses are what count - a filter the entity adds, soft delete's, would otherwise make
33
+ * every table look narrowed, which is the case this exists to catch.
34
+ */
35
+ function assertNamesRows(entity, method, q, opts) {
36
+ if (opts?.unfiltered || hasKeys(q?.$where) || q?.$limit !== undefined) {
37
+ return;
38
+ }
39
+ throw new TypeError(`'${method}' over '${entity.name}' names no rows, so it would address every one: pass '{ unfiltered: true }' to mean it`);
40
+ }
30
41
  /**
31
42
  * The id each written row is named by, in payload order. Read off the rows as written, so a key the
32
43
  * database generated or the ORM filled is there, and a composite is named by every column of it.
@@ -183,6 +194,7 @@ export class AbstractQuerier {
183
194
  }
184
195
  /** Settles the rows first where the update cascades, so a payload changing what `$where` reads still names them. */
185
196
  async updateMany(entity, q, payload, opts) {
197
+ assertNamesRows(entity, 'updateMany', q, opts);
186
198
  const meta = getMeta(entity);
187
199
  return this.hooked(entity, 'Update', [payload], async ([row]) => {
188
200
  fillOnFields(meta, [row], 'onUpdate');
@@ -206,9 +218,13 @@ export class AbstractQuerier {
206
218
  const writes = filterFieldKeys(getMeta(entity), row, 'onUpdate').length > 0;
207
219
  return writes ? this.internalUpdateMany(entity, q, row, opts) : unwritten;
208
220
  }
209
- /** Whether a write has to name the rows `q` matches by their ids: no engine pages or orders an update or delete. */
210
- settlesWrite(_entity, q) {
211
- return isPagedQuery(q);
221
+ /**
222
+ * Whether a write has to name the rows `q` matches by their ids: no engine pages or orders an update or
223
+ * delete, and one without {@link DialectFeatures.correlatedWrites} cannot read a relation in its filter.
224
+ */
225
+ settlesWrite(entity, q) {
226
+ const { dialect } = this;
227
+ return isPagedQuery(q) || (!dialect.features.correlatedWrites && dialect.constrainsRelations(entity, q.$where));
212
228
  }
213
229
  /** The ids `q` matches, in its own order and page. */
214
230
  async settleIds(entity, q, opts) {
@@ -254,6 +270,7 @@ export class AbstractQuerier {
254
270
  }
255
271
  async deleteMany(entityOrQuery, qOrOpts, maybeOpts) {
256
272
  const [entity, q, opts] = this.resolveEntityQuery(entityOrQuery, qOrOpts, maybeOpts);
273
+ assertNamesRows(entity, 'deleteMany', q, opts);
257
274
  const meta = getMeta(entity);
258
275
  const cascades = cascadesOnDelete(meta);
259
276
  const watched = this.hasHook(entity, 'beforeDelete') || this.hasHook(entity, 'afterDelete');
@@ -350,8 +367,7 @@ export class AbstractQuerier {
350
367
  const relOpts = relationOf(meta, relKey);
351
368
  const relEntity = relOpts.entity();
352
369
  const target = relOpts.through ? relOpts.through() : relEntity;
353
- const where = childrenOf(parentJoins(relOpts, meta.ids.length), ids);
354
- await this.deleteMany(target, { $where: where }, opts);
370
+ await this.deleteMany(target, { $where: childrenOf(parentJoins(relOpts, meta.ids.length), ids) }, opts);
355
371
  }
356
372
  }
357
373
  /**
@@ -480,8 +496,12 @@ export class AbstractQuerier {
480
496
  * the write filled in - a generated key, an `onInsert` value - without it landing on the caller's.
481
497
  */
482
498
  async hooked(entity, event, payloads, write) {
483
- await this.emitHook(entity, `before${event}`, payloads);
484
- const rows = clone(payloads);
499
+ // The one place a caller's write becomes the row the rest of the library handles. They are the
500
+ // same object: a write is the entity's data without the keys the database fills, which
501
+ // TypeScript cannot relate across an entity it has not resolved.
502
+ const asRows = payloads;
503
+ await this.emitHook(entity, `before${event}`, asRows);
504
+ const rows = clone(asRows);
485
505
  const result = await write(rows);
486
506
  await this.emitHook(entity, `after${event}`, rows);
487
507
  return result;
@@ -1,5 +1,5 @@
1
1
  import type { AbstractDialect } from '../dialect/index.js';
2
- import type { EntityData, EntityId, ExtraOptions, FieldKey, PoolRunOptions, Querier, QuerierPool, QueryAggMap, QueryAggregate, QueryAggregateResult, QueryConflictPaths, QueryFilter, QueryFindResult, QueryGroupMap, QueryOneProjected, QueryOptions, QueryPage, QueryProjected, QuerySearch, QueryUpsertOneResult, QueryUpsertManyResult, RelationKey, TransactionOptions, Type, UpdatePayload, WrittenId } from '../type/index.js';
2
+ import type { EntityWrite, EntityId, ExtraOptions, FieldKey, PoolRunOptions, Querier, QuerierPool, QueryAggMap, QueryAggregate, QueryAggregateResult, QueryConflictPaths, QueryFilter, QueryFindResult, QueryGroupMap, QueryOneProjected, QueryOptions, QueryPage, QueryProjected, QuerySearch, QueryUpsertOneResult, QueryUpsertManyResult, RelationKey, TransactionOptions, Type, UpdateWrite, WrittenId } from '../type/index.js';
3
3
  /**
4
4
  * Base pool: dialect id and behavior come only from the `dialect` instance (see {@link QuerierPool}).
5
5
  */
@@ -37,14 +37,14 @@ export declare abstract class AbstractQuerierPool<Q extends Querier, D extends A
37
37
  exists<E extends object>(entity: Type<E>, q?: QueryFilter<E>, opts?: QueryOptions): Promise<boolean>;
38
38
  aggregate<E extends object, const G extends QueryGroupMap<E>, const A extends QueryAggMap<E>>(entity: Type<E>, q: QueryAggregate<E, G, A>, opts?: QueryOptions): Promise<QueryAggregateResult<E, G, A>[]>;
39
39
  estimatedCount<E extends object>(entity: Type<E>): Promise<number>;
40
- insertOne<E extends object>(entity: Type<E>, payload: EntityData<E>): Promise<WrittenId<E> | undefined>;
41
- insertMany<E extends object>(entity: Type<E>, payload: EntityData<E>[]): Promise<(WrittenId<E> | undefined)[]>;
42
- updateOneById<E extends object>(entity: Type<E>, id: EntityId<E>, payload: UpdatePayload<E>, opts?: QueryOptions): Promise<number>;
43
- updateMany<E extends object>(entity: Type<E>, q: QuerySearch<E>, payload: UpdatePayload<E>, opts?: QueryOptions): Promise<number>;
44
- upsertOne<E extends object>(entity: Type<E>, conflictPaths: QueryConflictPaths<E>, payload: EntityData<E>): Promise<QueryUpsertOneResult<E>>;
45
- upsertMany<E extends object>(entity: Type<E>, conflictPaths: QueryConflictPaths<E>, payload: EntityData<E>[]): Promise<QueryUpsertManyResult<E>>;
46
- saveOne<E extends object>(entity: Type<E>, payload: EntityData<E>): Promise<WrittenId<E> | undefined>;
47
- saveMany<E extends object>(entity: Type<E>, payload: EntityData<E>[]): Promise<(WrittenId<E> | undefined)[]>;
40
+ insertOne<E extends object>(entity: Type<E>, payload: EntityWrite<E>): Promise<WrittenId<E> | undefined>;
41
+ insertMany<E extends object>(entity: Type<E>, payload: EntityWrite<E>[]): Promise<(WrittenId<E> | undefined)[]>;
42
+ updateOneById<E extends object>(entity: Type<E>, id: EntityId<E>, payload: UpdateWrite<E>, opts?: QueryOptions): Promise<number>;
43
+ updateMany<E extends object>(entity: Type<E>, q: QuerySearch<E>, payload: UpdateWrite<E>, opts?: QueryOptions): Promise<number>;
44
+ upsertOne<E extends object>(entity: Type<E>, conflictPaths: QueryConflictPaths<E>, payload: EntityWrite<E>): Promise<QueryUpsertOneResult<E>>;
45
+ upsertMany<E extends object>(entity: Type<E>, conflictPaths: QueryConflictPaths<E>, payload: EntityWrite<E>[]): Promise<QueryUpsertManyResult<E>>;
46
+ saveOne<E extends object>(entity: Type<E>, payload: EntityWrite<E>): Promise<WrittenId<E> | undefined>;
47
+ saveMany<E extends object>(entity: Type<E>, payload: EntityWrite<E>[]): Promise<(WrittenId<E> | undefined)[]>;
48
48
  deleteOneById<E extends object>(entity: Type<E>, id: EntityId<E>, opts?: QueryOptions): Promise<number>;
49
49
  deleteMany<E extends object>(entity: Type<E>, q: QuerySearch<E>, opts?: QueryOptions): Promise<number>;
50
50
  restoreOneById<E extends object>(entity: Type<E>, id: EntityId<E>): Promise<number>;
@@ -80,7 +80,7 @@ export declare abstract class AbstractSqlQuerier extends AbstractQuerier impleme
80
80
  */
81
81
  private hydrateFields;
82
82
  /**
83
- * Runs a statement whose one row carries a {@link COUNT_ALIAS} column. `Number` because `COUNT(*)` is BIGINT and
83
+ * Runs a statement whose one row carries a {@link AGGREGATE_VALUE_ALIAS} column. `Number` because `COUNT(*)` is BIGINT and
84
84
  * a caller supplying their own `types` replaces the decoding the pools do at the wire; `?? 0` because
85
85
  * a catalog that does not know the table answers with no row, which is nothing counted.
86
86
  */
@@ -1,4 +1,4 @@
1
- import { COUNT_ALIAS, TOTAL_ALIAS } from '../dialect/aliases.js';
1
+ import { AGGREGATE_VALUE_ALIAS, TOTAL_ALIAS } from '../dialect/aliases.js';
2
2
  import { decodeColumn } from '../dialect/hydrateColumn.js';
3
3
  import { getMeta, namesKey } from '../entity/index.js';
4
4
  import { COUNT_RESULT_KEY } from '../type/index.js';
@@ -290,13 +290,13 @@ export class AbstractSqlQuerier extends AbstractQuerier {
290
290
  }
291
291
  }
292
292
  /**
293
- * Runs a statement whose one row carries a {@link COUNT_ALIAS} column. `Number` because `COUNT(*)` is BIGINT and
293
+ * Runs a statement whose one row carries a {@link AGGREGATE_VALUE_ALIAS} column. `Number` because `COUNT(*)` is BIGINT and
294
294
  * a caller supplying their own `types` replaces the decoding the pools do at the wire; `?? 0` because
295
295
  * a catalog that does not know the table answers with no row, which is nothing counted.
296
296
  */
297
297
  async runCount(build) {
298
298
  const [row] = await this.query(build);
299
- return Number(row?.[COUNT_ALIAS] ?? 0);
299
+ return Number(row?.[AGGREGATE_VALUE_ALIAS] ?? 0);
300
300
  }
301
301
  async internalCount(entity, q, opts) {
302
302
  return this.runCount((ctx) => this.dialect.count(ctx, entity, q, opts));
@@ -80,6 +80,7 @@ const SQL_TO_CANONICAL = {
80
80
  image: { category: 'blob', size: 'big' },
81
81
  // === Vector (for AI/embeddings) ===
82
82
  vector: { category: 'vector' },
83
+ f32_blob: { category: 'vector' },
83
84
  halfvec: { category: 'halfvec' },
84
85
  sparsevec: { category: 'sparsevec' },
85
86
  };
@@ -204,8 +205,8 @@ const ENGINE_TYPES = {
204
205
  sizes: MYSQL_SIZES,
205
206
  decimal: { precision: 10, scale: 2 },
206
207
  },
207
- // SQLite uses affinity, so no size variants.
208
- sqlite: { scalars: withVectorType(SQLITE_SCALAR_MAP, 'TEXT') },
208
+ // SQLite uses affinity, so no size variants. `F32_BLOB` is libSQL's vector type; elsewhere just a name of BLOB affinity.
209
+ sqlite: { scalars: withVectorType(SQLITE_SCALAR_MAP, 'F32_BLOB') },
209
210
  // 2025 and up; below that the server refuses the type rather than storing it as text.
210
211
  mssql: { scalars: withVectorType(MSSQL_SCALAR_MAP, 'VECTOR'), sizes: MSSQL_SIZES },
211
212
  mongodb: { scalars: withVectorType(MONGO_SCALAR_MAP, 'array') },
@@ -238,7 +239,7 @@ export function sqlToCanonical(sqlType) {
238
239
  const unsigned = normalized.includes('unsigned');
239
240
  const withoutUnsigned = normalized.replace(/\s*unsigned\s*/i, ' ').trim();
240
241
  // Extract base type and parameters: "VARCHAR(255)" -> ["varchar", "255"]
241
- const match = withoutUnsigned.match(/^([a-z][a-z0-9 ]*?)(?:\(([^)]+)\))?$/);
242
+ const match = withoutUnsigned.match(/^([a-z][a-z0-9_ ]*?)(?:\(([^)]+)\))?$/);
242
243
  const base = match ? SQL_TO_CANONICAL[match[1]] : undefined;
243
244
  if (!match || !base) {
244
245
  return { category: 'string', raw: sqlType };
@@ -332,8 +333,13 @@ export function canonicalToTypeScript(type) {
332
333
  * the engine settles an unstated bound. Migrations and drift both compare through it.
333
334
  */
334
335
  export function engineType(dialect) {
335
- return (type) => sqlToCanonical(canonicalToSql(type, dialect));
336
+ return (type) => {
337
+ const stored = sqlToCanonical(canonicalToSql(type, dialect));
338
+ // SQLite keeps a vector in any column, so one created as `TEXT` before vectors were blobs stays as it is.
339
+ return dialect.dialectName === 'sqlite' && isVectorCategory(stored.category) ? SQLITE_TEXT : stored;
340
+ };
336
341
  }
342
+ const SQLITE_TEXT = { category: 'string', size: 'small' };
337
343
  /**
338
344
  * Convert UQL FieldOptions to a canonical type.
339
345
  */
@@ -1,6 +1,9 @@
1
1
  import type { IndexNode } from './types.js';
2
- /** What an introspector reports about an index, and so all a diff may compare; apart from `IndexFeature`, what an engine emits. */
3
- export type IndexFacet = 'order' | 'nulls' | 'opsClass' | 'accessMethod' | 'include';
2
+ /**
3
+ * What an introspector reports about an index, and so all a diff may compare; apart from `IndexFeature`, what an engine emits.
4
+ * `vector` is whether it is a vector index at all, for an engine with one vector index whatever type declared it.
5
+ */
6
+ export type IndexFacet = 'order' | 'nulls' | 'opsClass' | 'accessMethod' | 'include' | 'vector';
4
7
  /**
5
8
  * Whether the table has this index already, by shape rather than name, uniqueness included. An index
6
9
  * over an expression, whose text the engine reprints, falls back to its name.
@@ -1,3 +1,4 @@
1
+ import { isVectorIndexType } from '../type/vector.js';
1
2
  /**
2
3
  * Whether the table has this index already, by shape rather than name, uniqueness included. An index
3
4
  * over an expression, whose text the engine reprints, falls back to its name.
@@ -45,6 +46,10 @@ export function describeIndexDifferences(source, target, facets) {
45
46
  if (facets.has('accessMethod') && (source.type ?? 'btree') !== (target.type ?? 'btree')) {
46
47
  differences.push(`type: ${target.type ?? 'btree'} -> ${source.type ?? 'btree'}`);
47
48
  }
49
+ if (facets.has('vector') && isVectorIndexType(source.type) !== isVectorIndexType(target.type)) {
50
+ const [expected, actual] = [source, target].map((index) => (isVectorIndexType(index.type) ? 'yes' : 'no'));
51
+ differences.push(`vector index: ${actual} -> ${expected}`);
52
+ }
48
53
  if (facets.has('include')) {
49
54
  // Order carries no meaning in an `INCLUDE` list, so it is compared as a set.
50
55
  const [sourceInclude, targetInclude] = [source.include ?? [], target.include ?? []].map((columns) => [...columns].sort().join(', '));
@@ -1,5 +1,5 @@
1
1
  import { fieldOf, foreignKeysOf, getMeta, soleIdOf } from '../entity/metadata/definition.js';
2
- import { declaredIndexes, indexNameParts, renderIndexColumn } from '../util/ddlExpression.util.js';
2
+ import { declaredIndexes, declaredIndexName, renderIndexColumn } from '../util/ddlExpression.util.js';
3
3
  import { isInlinedExpression } from '../util/field.util.js';
4
4
  import { isSoleIdField } from '../util/field.util.js';
5
5
  import { isAutoIncrement } from '../util/field.util.js';
@@ -198,7 +198,7 @@ function addCompositeIndex(ctx, table, meta, idxMeta) {
198
198
  });
199
199
  if (!resolved.length)
200
200
  return;
201
- const name = idxMeta.name ?? derivedIndexName(table.name, indexNameParts(resolved));
201
+ const name = declaredIndexName(idxMeta.name, table.name, resolved);
202
202
  ctx.ast.addIndex({
203
203
  name,
204
204
  table,
@@ -211,5 +211,6 @@ function addCompositeIndex(ctx, table, meta, idxMeta) {
211
211
  m: idxMeta.m,
212
212
  efConstruction: idxMeta.efConstruction,
213
213
  lists: idxMeta.lists,
214
+ config: idxMeta.config,
214
215
  });
215
216
  }
@@ -1,7 +1,6 @@
1
1
  import { AbstractSharedHandleQuerierPool } from '../querier/abstractSharedHandleQuerierPool.js';
2
- import type { ExtraOptions } from '../type/index.js';
3
- import { SqliteDialect } from './sqliteDialect.js';
4
- import { type SqlitePreparedStatement, SqliteQuerier } from './sqliteQuerier.js';
2
+ import type { SqliteDialect } from './sqliteDialect.js';
3
+ import { type SqliteDatabase, type SqlitePreparedStatement, SqliteQuerier } from './sqliteQuerier.js';
5
4
  /** What every local SQLite pool accepts on top of its driver's own options. */
6
5
  export type LocalSqlitePoolOptions = {
7
6
  /**
@@ -27,12 +26,12 @@ export type LocalSqliteDatabase = {
27
26
  export declare function adaptSqlite<S extends Omit<SqlitePreparedStatement, 'reader'>>(db: Omit<LocalSqliteDatabase, 'prepare'> & {
28
27
  prepare(sql: string): S;
29
28
  }, reads: (stmt: S) => boolean): LocalSqliteDatabase;
30
- /** A pool for a SQLite file opened in this process, configured the same way whichever driver's {@link createDb} opens it. */
31
- export declare abstract class AbstractLocalSqliteQuerierPool<O extends LocalSqlitePoolOptions> extends AbstractSharedHandleQuerierPool<LocalSqliteDatabase, SqliteQuerier, SqliteDialect> {
32
- readonly opts?: O | undefined;
33
- constructor(opts?: O | undefined, extra?: ExtraOptions);
34
- /** Opens the driver's database, and nothing more: the caller configures it. */
35
- protected abstract createDb(): Promise<LocalSqliteDatabase>;
36
- protected openDb(): Promise<LocalSqliteDatabase>;
37
- protected buildQuerier(db: LocalSqliteDatabase): SqliteQuerier;
29
+ /** `db` with each loadable extension installed, which `node:sqlite` refuses unless opened to allow them. */
30
+ export declare function loadExtensions(db: LocalSqliteDatabase, extensions?: readonly string[]): LocalSqliteDatabase;
31
+ /** A pool for a database file opened in this process, configured the same way whichever driver's {@link createDb} opens it. */
32
+ export declare abstract class AbstractLocalSqliteQuerierPool<DB extends SqliteDatabase, D extends SqliteDialect> extends AbstractSharedHandleQuerierPool<DB, SqliteQuerier, D> {
33
+ /** Opens the driver's database, reading integers as `bigint`, which the querier decodes exactly past 2^53. */
34
+ protected abstract createDb(): Promise<DB>;
35
+ protected openDb(): Promise<DB>;
36
+ protected buildQuerier(db: DB): SqliteQuerier;
38
37
  }
@@ -1,6 +1,4 @@
1
- import { dialectOptionsFrom } from '../dialect/abstractDialect.js';
2
1
  import { AbstractSharedHandleQuerierPool } from '../querier/abstractSharedHandleQuerierPool.js';
3
- import { SqliteDialect } from './sqliteDialect.js';
4
2
  import { applySqlitePragmas } from './sqlitePragmas.js';
5
3
  import { SqliteQuerier } from './sqliteQuerier.js';
6
4
  /**
@@ -22,19 +20,18 @@ export function adaptSqlite(db, reads) {
22
20
  close: () => db.close(),
23
21
  };
24
22
  }
25
- /** A pool for a SQLite file opened in this process, configured the same way whichever driver's {@link createDb} opens it. */
26
- export class AbstractLocalSqliteQuerierPool extends AbstractSharedHandleQuerierPool {
27
- opts;
28
- constructor(opts, extra) {
29
- super(new SqliteDialect(dialectOptionsFrom(extra)), extra);
30
- this.opts = opts;
23
+ /** `db` with each loadable extension installed, which `node:sqlite` refuses unless opened to allow them. */
24
+ export function loadExtensions(db, extensions = []) {
25
+ for (const extension of extensions) {
26
+ db.loadExtension(extension);
31
27
  }
28
+ return db;
29
+ }
30
+ /** A pool for a database file opened in this process, configured the same way whichever driver's {@link createDb} opens it. */
31
+ export class AbstractLocalSqliteQuerierPool extends AbstractSharedHandleQuerierPool {
32
32
  async openDb() {
33
33
  const db = await this.createDb();
34
34
  await applySqlitePragmas(db);
35
- for (const extension of this.opts?.extensions ?? []) {
36
- db.loadExtension(extension);
37
- }
38
35
  return db;
39
36
  }
40
37
  buildQuerier(db) {
@@ -1,5 +1,6 @@
1
1
  import type { ExtraOptions } from '../type/index.js';
2
2
  import { AbstractLocalSqliteQuerierPool, type LocalSqliteDatabase, type LocalSqlitePoolOptions } from './localSqliteQuerierPool.js';
3
+ import { SqliteDialect } from './sqliteDialect.js';
3
4
  /**
4
5
  * The `DatabaseSync` options worth surfacing, plus the loadable extensions to install. Declared here
5
6
  * rather than imported from `node:sqlite` so this module needs no ambient Node types; unknown keys
@@ -15,8 +16,9 @@ export type NodeSqlitePoolOptions = LocalSqlitePoolOptions & {
15
16
  * A pool over Node's built-in `node:sqlite`, needing no dependency at all. {@link Sqlite3QuerierPool} is the
16
17
  * faster choice for read-heavy work, and the one on Bun.
17
18
  */
18
- export declare class NodeSqliteQuerierPool extends AbstractLocalSqliteQuerierPool<NodeSqlitePoolOptions> {
19
+ export declare class NodeSqliteQuerierPool extends AbstractLocalSqliteQuerierPool<LocalSqliteDatabase, SqliteDialect> {
19
20
  readonly filename: string;
20
- constructor(filename?: string, opts?: NodeSqlitePoolOptions, extra?: ExtraOptions);
21
+ readonly opts?: NodeSqlitePoolOptions | undefined;
22
+ constructor(filename?: string, opts?: NodeSqlitePoolOptions | undefined, extra?: ExtraOptions);
21
23
  protected createDb(): Promise<LocalSqliteDatabase>;
22
24
  }
@@ -1,24 +1,27 @@
1
- import { AbstractLocalSqliteQuerierPool, adaptSqlite, } from './localSqliteQuerierPool.js';
1
+ import { dialectOptionsFrom } from '../dialect/abstractDialect.js';
2
+ import { AbstractLocalSqliteQuerierPool, adaptSqlite, loadExtensions, } from './localSqliteQuerierPool.js';
3
+ import { SqliteDialect } from './sqliteDialect.js';
2
4
  /**
3
5
  * A pool over Node's built-in `node:sqlite`, needing no dependency at all. {@link Sqlite3QuerierPool} is the
4
6
  * faster choice for read-heavy work, and the one on Bun.
5
7
  */
6
8
  export class NodeSqliteQuerierPool extends AbstractLocalSqliteQuerierPool {
7
9
  filename;
10
+ opts;
8
11
  constructor(filename = ':memory:', opts, extra) {
9
- super(opts, extra);
12
+ super(new SqliteDialect(dialectOptionsFrom(extra)), extra);
10
13
  this.filename = filename;
14
+ this.opts = opts;
11
15
  }
12
16
  async createDb() {
13
17
  const { DatabaseSync } = await import('node:sqlite');
14
18
  const { extensions, ...driverOpts } = this.opts ?? {};
15
19
  const nodeDb = new DatabaseSync(this.filename, {
16
20
  ...driverOpts,
17
- // Integers as `bigint`, which the querier decodes exactly past 2^53.
18
21
  readBigInts: true,
19
22
  // `node:sqlite` refuses `loadExtension` unless the database was opened with this on.
20
23
  ...(extensions?.length ? { allowExtension: true } : undefined),
21
24
  });
22
- return adaptSqlite(nodeDb, (stmt) => stmt.columns().length > 0);
25
+ return loadExtensions(adaptSqlite(nodeDb, (stmt) => stmt.columns().length > 0), extensions);
23
26
  }
24
27
  }
@@ -1,6 +1,6 @@
1
1
  import { AbstractSqlDialect, type DerivedRelation, type HydrateKind, type RelationRows } from '../dialect/abstractSqlDialect.js';
2
2
  import { type JsonAccessMode, type JsonSlot } from '../dialect/jsonSql.js';
3
- import type { EntityMeta, FieldOptions, QueryContext, QueryPager, QueryTextSearchOptions, SqlDialectFeatures, Type, VectorDistance, VectorMetric } from '../type/index.js';
3
+ import { type EntityMeta, type FieldOptions, type Query, type QueryContext, type QueryPager, type QueryTextSearchOptions, type QueryWhere, type SqlDialectFeatures, type Type, type VectorDistance, type VectorMetric } from '../type/index.js';
4
4
  /** What SQLite and the engines derived from it have. */
5
5
  export declare const SQLITE_FEATURES: SqlDialectFeatures;
6
6
  export declare class SqliteDialect extends AbstractSqlDialect {
@@ -24,6 +24,12 @@ export declare class SqliteDialect extends AbstractSqlDialect {
24
24
  * their own vector functions instead, so `LibsqlDialect` overrides this.
25
25
  */
26
26
  readonly vectorMetrics: ReadonlyMap<VectorDistance, VectorMetric>;
27
+ /**
28
+ * A read ranked by the metric its field's vector index measures, and paged, narrowed to the rowids of
29
+ * that index's nearest rows, which libSQL's `vector_top_k` answers: `$candidates` of them, else as many
30
+ * as the page reaches. Their exact distance still orders them. Unchanged on an engine with no such index.
31
+ */
32
+ protected rankedWhere<E>(meta: EntityMeta<E>, q: Query<E>, prefix: string | undefined): QueryWhere<E> | undefined;
27
33
  /**
28
34
  * SQLite does not support the `DEFAULT` keyword inside `VALUES`. Inline the metadata default
29
35
  * when declared, else `NULL` (which is also how SQLite auto-generates INTEGER PRIMARY KEYs).
@@ -51,7 +57,9 @@ export declare class SqliteDialect extends AbstractSqlDialect {
51
57
  protected readonly carriedFields: {
52
58
  numeric: (expr: string, field: FieldOptions) => string;
53
59
  blob: (expr: string) => string;
60
+ vector: (expr: string) => string;
54
61
  };
62
+ private bytesAsText;
55
63
  /** A date reads back as SQLite stored it, a number or text, which JSON carries unchanged. */
56
64
  protected hydrateKind(field: FieldOptions | undefined): HydrateKind | undefined;
57
65
  /**
@@ -1,7 +1,10 @@
1
1
  import { AbstractSqlDialect, } from '../dialect/abstractSqlDialect.js';
2
2
  import { BYTES_PREFIX } from '../dialect/hydrateColumn.js';
3
3
  import { chainedCall, groupsPerCall, jsonSetCall, jsonPath, jsonArraySlotArgs, jsonSlotArgs, jsonRemoveCall, jsonSetTarget, } from '../dialect/jsonSql.js';
4
- import { textSearchFields } from '../util/dialect.util.js';
4
+ import { QueryRaw, } from '../type/index.js';
5
+ import { indexDistance, isVectorIndexType } from '../type/vector.js';
6
+ import { declaredIndexName } from '../util/ddlExpression.util.js';
7
+ import { findVectorIndex, findVectorSort, textSearchFields, vectorCandidates } from '../util/dialect.util.js';
5
8
  import { columnFamily, isIntegerColumn } from '../util/field.util.js';
6
9
  /** What SQLite and the engines derived from it have. */
7
10
  export const SQLITE_FEATURES = {
@@ -14,11 +17,13 @@ export const SQLITE_FEATURES = {
14
17
  generatedColumnAdd: false, // accepted in a CREATE TABLE, rejected in an ALTER
15
18
  commentSyntax: 'none',
16
19
  vectorIndexRequiresNotNull: false,
17
- vectorSupportsLength: false,
20
+ vectorSupportsLength: true,
21
+ vectorBytes: true,
18
22
  supportsTimestamptz: false,
19
23
  stringSizing: 'text',
20
24
  supportsUnsigned: false,
21
25
  serverSideCursors: false,
26
+ correlatedWrites: true,
22
27
  rowLocks: false,
23
28
  rowLockWithWindow: true,
24
29
  rowLockOf: true,
@@ -54,6 +59,37 @@ export class SqliteDialect extends AbstractSqlDialect {
54
59
  ['l2', { fn: 'vec_distance_L2' }],
55
60
  ['l1', { fn: 'vec_distance_L1' }],
56
61
  ]);
62
+ /**
63
+ * A read ranked by the metric its field's vector index measures, and paged, narrowed to the rowids of
64
+ * that index's nearest rows, which libSQL's `vector_top_k` answers: `$candidates` of them, else as many
65
+ * as the page reaches. Their exact distance still orders them. Unchanged on an engine with no such index.
66
+ */
67
+ rankedWhere(meta, q, prefix) {
68
+ const ranked = findVectorSort(q.$sort);
69
+ const k = vectorCandidates(q) ?? (q.$limit === undefined ? undefined : (q.$skip ?? 0) + q.$limit);
70
+ const index = ranked && findVectorIndex(meta, ranked.key);
71
+ if (!ranked || !index || !isVectorIndexType(index.type) || k === undefined) {
72
+ return q.$where;
73
+ }
74
+ const { colName, distance, field } = this.resolveVectorDistance(meta, ranked.key, ranked.search);
75
+ if (indexDistance(index) !== distance || !this.vectorMetrics.get(distance)?.index) {
76
+ return q.$where;
77
+ }
78
+ const name = declaredIndexName(index.name, this.resolveTableName(meta), [{ column: colName }]);
79
+ const table = this.escapeId(prefix ?? this.resolveTableAlias(meta), true, true);
80
+ const nearest = new QueryRaw(({ ctx }) => {
81
+ ctx.append(`${table}rowid IN (SELECT id FROM vector_top_k(`);
82
+ ctx.addValue(name);
83
+ ctx.append(', ');
84
+ this.appendVectorValue(ctx, ranked.search.$vector, field);
85
+ ctx.append(', ');
86
+ ctx.addValue(k);
87
+ ctx.append('))');
88
+ });
89
+ const where = {};
90
+ where.$and = q.$where ? [q.$where, nearest] : [nearest];
91
+ return where;
92
+ }
57
93
  /**
58
94
  * SQLite does not support the `DEFAULT` keyword inside `VALUES`. Inline the metadata default
59
95
  * when declared, else `NULL` (which is also how SQLite auto-generates INTEGER PRIMARY KEYs).
@@ -108,8 +144,12 @@ export class SqliteDialect extends AbstractSqlDialect {
108
144
  */
109
145
  carriedFields = {
110
146
  numeric: (expr, field) => (isIntegerColumn(field) ? `CAST(${expr} AS TEXT)` : expr),
111
- blob: (expr) => `${this.escape(BYTES_PREFIX)} || hex(${expr})`,
147
+ blob: (expr) => this.bytesAsText(expr),
148
+ vector: (expr) => `CASE WHEN typeof(${expr}) = 'blob' THEN ${this.bytesAsText(expr)} ELSE ${expr} END`,
112
149
  };
150
+ bytesAsText(expr) {
151
+ return `${this.escape(BYTES_PREFIX)} || hex(${expr})`;
152
+ }
113
153
  /** A date reads back as SQLite stored it, a number or text, which JSON carries unchanged. */
114
154
  hydrateKind(field) {
115
155
  return columnFamily(field?.type) === 'date' ? undefined : super.hydrateKind(field);
@@ -1,19 +1,20 @@
1
1
  import type { Options } from 'better-sqlite3';
2
2
  import type { ExtraOptions } from '../type/index.js';
3
3
  import { AbstractLocalSqliteQuerierPool, type LocalSqliteDatabase, type LocalSqlitePoolOptions } from './localSqliteQuerierPool.js';
4
+ import { SqliteDialect } from './sqliteDialect.js';
4
5
  /** Driver options, plus the loadable extensions to install on the connection. */
5
6
  export type Sqlite3PoolOptions = Options & LocalSqlitePoolOptions;
6
7
  /**
7
8
  * Pool for `better-sqlite3`, or `bun:sqlite` when running under Bun - the same file, through whichever
8
9
  * driver the runtime provides.
9
10
  */
10
- export declare class Sqlite3QuerierPool extends AbstractLocalSqliteQuerierPool<Sqlite3PoolOptions> {
11
+ export declare class Sqlite3QuerierPool extends AbstractLocalSqliteQuerierPool<LocalSqliteDatabase, SqliteDialect> {
11
12
  readonly filename: string | Buffer;
12
- constructor(filename?: string | Buffer, opts?: Sqlite3PoolOptions, extra?: ExtraOptions);
13
+ readonly opts?: Sqlite3PoolOptions | undefined;
14
+ constructor(filename?: string | Buffer, opts?: Sqlite3PoolOptions | undefined, extra?: ExtraOptions);
13
15
  /**
14
- * Both drivers read integers as `bigint`, which the querier decodes exactly past 2^53. `bun:sqlite`
15
- * rejects option keys it does not know, so `extensions` is stripped out, and opens only a path, so a
16
- * serialized database - which better-sqlite3 takes as its filename - is deserialized there instead.
16
+ * `bun:sqlite` rejects option keys it does not know, so `extensions` is stripped out, and opens only a
17
+ * path, so a serialized database - which better-sqlite3 takes as its filename - is deserialized there instead.
17
18
  */
18
19
  protected createDb(): Promise<LocalSqliteDatabase>;
19
20
  }
@@ -1,18 +1,21 @@
1
- import { AbstractLocalSqliteQuerierPool, adaptSqlite, } from './localSqliteQuerierPool.js';
1
+ import { dialectOptionsFrom } from '../dialect/abstractDialect.js';
2
+ import { AbstractLocalSqliteQuerierPool, adaptSqlite, loadExtensions, } from './localSqliteQuerierPool.js';
3
+ import { SqliteDialect } from './sqliteDialect.js';
2
4
  /**
3
5
  * Pool for `better-sqlite3`, or `bun:sqlite` when running under Bun - the same file, through whichever
4
6
  * driver the runtime provides.
5
7
  */
6
8
  export class Sqlite3QuerierPool extends AbstractLocalSqliteQuerierPool {
7
9
  filename;
10
+ opts;
8
11
  constructor(filename = ':memory:', opts, extra) {
9
- super(opts, extra);
12
+ super(new SqliteDialect(dialectOptionsFrom(extra)), extra);
10
13
  this.filename = filename;
14
+ this.opts = opts;
11
15
  }
12
16
  /**
13
- * Both drivers read integers as `bigint`, which the querier decodes exactly past 2^53. `bun:sqlite`
14
- * rejects option keys it does not know, so `extensions` is stripped out, and opens only a path, so a
15
- * serialized database - which better-sqlite3 takes as its filename - is deserialized there instead.
17
+ * `bun:sqlite` rejects option keys it does not know, so `extensions` is stripped out, and opens only a
18
+ * path, so a serialized database - which better-sqlite3 takes as its filename - is deserialized there instead.
16
19
  */
17
20
  async createDb() {
18
21
  const { extensions, ...driverOpts } = this.opts ?? {};
@@ -22,9 +25,9 @@ export class Sqlite3QuerierPool extends AbstractLocalSqliteQuerierPool {
22
25
  const bunDb = typeof this.filename === 'string'
23
26
  ? new Database(this.filename, bunOpts)
24
27
  : Database.deserialize(this.filename, bunOpts);
25
- return adaptSqlite(bunDb, (stmt) => stmt.columnNames.length > 0);
28
+ return loadExtensions(adaptSqlite(bunDb, (stmt) => stmt.columnNames.length > 0), extensions);
26
29
  }
27
30
  const { default: BetterSqlite3 } = await import('better-sqlite3');
28
- return new BetterSqlite3(this.filename, driverOpts).defaultSafeIntegers(true);
31
+ return loadExtensions(new BetterSqlite3(this.filename, driverOpts).defaultSafeIntegers(true), extensions);
29
32
  }
30
33
  }
@@ -5,6 +5,6 @@ import type { SqlDialectFeatures } from '../type/index.js';
5
5
  * `ORDER BY` inside an aggregate, which its Rust engine lacks. Imports no driver.
6
6
  */
7
7
  export declare class TursoDialect extends LibsqlDialect {
8
- /** The Rust engine takes no `ORDER BY` inside an aggregate. */
8
+ /** The Rust engine takes no `ORDER BY` inside an aggregate, nor a subquery reading the table a write changes. */
9
9
  readonly features: SqlDialectFeatures;
10
10
  }
@@ -5,6 +5,10 @@ import { SQLITE_FEATURES } from '../sqlite/sqliteDialect.js';
5
5
  * `ORDER BY` inside an aggregate, which its Rust engine lacks. Imports no driver.
6
6
  */
7
7
  export class TursoDialect extends LibsqlDialect {
8
- /** The Rust engine takes no `ORDER BY` inside an aggregate. */
9
- features = { ...SQLITE_FEATURES, orderedJsonAggregates: false };
8
+ /** The Rust engine takes no `ORDER BY` inside an aggregate, nor a subquery reading the table a write changes. */
9
+ features = {
10
+ ...SQLITE_FEATURES,
11
+ orderedJsonAggregates: false,
12
+ correlatedWrites: false,
13
+ };
10
14
  }
@@ -2,7 +2,7 @@ import type { VectorDistance, VectorMetric } from '../type/index.js';
2
2
  import { TursoDialect } from './tursoDialect.js';
3
3
  /**
4
4
  * SQLite Dialect specialization for the embedded Turso engine, the Rust engine alone: it adds a
5
- * dot-product distance to libSQL's cosine and L2, and caps no function call.
5
+ * dot-product distance to libSQL's cosine and L2, caps no function call, and has no vector index.
6
6
  */
7
7
  export declare class TursoLocalDialect extends TursoDialect {
8
8
  readonly vectorMetrics: ReadonlyMap<VectorDistance, VectorMetric>;
@@ -1,7 +1,7 @@
1
1
  import { TursoDialect } from './tursoDialect.js';
2
2
  /**
3
3
  * SQLite Dialect specialization for the embedded Turso engine, the Rust engine alone: it adds a
4
- * dot-product distance to libSQL's cosine and L2, and caps no function call.
4
+ * dot-product distance to libSQL's cosine and L2, caps no function call, and has no vector index.
5
5
  */
6
6
  export class TursoLocalDialect extends TursoDialect {
7
7
  vectorMetrics = new Map([
@@ -1,15 +1,14 @@
1
1
  import type { connect } from '@tursodatabase/database';
2
- import { AbstractSharedHandleQuerierPool } from '../querier/abstractSharedHandleQuerierPool.js';
3
- import { type SqliteDatabase, SqliteQuerier } from '../sqlite/sqliteQuerier.js';
2
+ import { AbstractLocalSqliteQuerierPool } from '../sqlite/localSqliteQuerierPool.js';
3
+ import type { SqliteDatabase } from '../sqlite/sqliteQuerier.js';
4
4
  import type { ExtraOptions } from '../type/index.js';
5
5
  import { TursoLocalDialect } from './tursoLocalDialect.js';
6
6
  /** The engine's own options: `readonly`, `timeout`, `encryption`, `experimental` and the rest. */
7
7
  export type TursoLocalOptions = NonNullable<Parameters<typeof connect>[1]>;
8
8
  /** A pool for the embedded Turso engine, on `uql-orm/turso/local` so its native binaries stay out of edge bundles. */
9
- export declare class TursoLocalQuerierPool extends AbstractSharedHandleQuerierPool<SqliteDatabase, SqliteQuerier, TursoLocalDialect> {
9
+ export declare class TursoLocalQuerierPool extends AbstractLocalSqliteQuerierPool<SqliteDatabase, TursoLocalDialect> {
10
10
  readonly filename: string;
11
11
  readonly opts?: TursoLocalOptions | undefined;
12
12
  constructor(filename?: string, opts?: TursoLocalOptions | undefined, extra?: ExtraOptions);
13
- protected openDb(): Promise<SqliteDatabase>;
14
- protected buildQuerier(db: SqliteDatabase): SqliteQuerier;
13
+ protected createDb(): Promise<SqliteDatabase>;
15
14
  }