@atscript/db-sqlite 0.1.145 → 0.1.147

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/dist/index.cjs CHANGED
@@ -86,7 +86,8 @@ var BetterSqlite3Driver = class {
86
86
  //#region src/calendar-bucket.ts
87
87
  /**
88
88
  * Name of the scalar SQL function the adapter registers on its driver:
89
- * `atscript_bucket(value, unit, tz, weekStart)` → TEXT `'YYYY-MM-DD'` or NULL.
89
+ * `atscript_bucket(value, unit, tz, weekStart)` → TEXT `'YYYY-MM-DD'`
90
+ * (`'YYYY-MM-DDTHH:00'` for unit `hour`) or NULL.
90
91
  */
91
92
  const SQLITE_BUCKET_FN = "atscript_bucket";
92
93
  /**
@@ -287,6 +288,7 @@ const sqliteDialect = {
287
288
  },
288
289
  calendarBucket: sqliteCalendarBucket,
289
290
  jsonExtract: sqliteJsonExtract,
291
+ castDouble: (expr) => `CAST(${expr} AS REAL)`,
290
292
  createViewPrefix: "CREATE VIEW IF NOT EXISTS"
291
293
  };
292
294
  /**
@@ -438,8 +440,9 @@ function buildCreateTable(table, fields, foreignKeys, options) {
438
440
  colDefs.push(`PRIMARY KEY (${pkCols})`);
439
441
  }
440
442
  if (foreignKeys) for (const fk of foreignKeys.values()) {
441
- const localCols = fk.fields.map((f) => `"${esc(f)}"`).join(", ");
442
- const targetCols = fk.targetFields.map((f) => `"${esc(f)}"`).join(", ");
443
+ const { fields, targetFields } = (0, _atscript_db.fkColumns)(fk);
444
+ const localCols = fields.map((f) => `"${esc(f)}"`).join(", ");
445
+ const targetCols = targetFields.map((f) => `"${esc(f)}"`).join(", ");
443
446
  let constraint = `FOREIGN KEY (${localCols}) REFERENCES "${esc(fk.targetTable)}" (${targetCols})`;
444
447
  if (fk.onDelete) constraint += ` ON DELETE ${(0, _atscript_db_sql_tools.refActionToSql)(fk.onDelete)}`;
445
448
  if (fk.onUpdate) constraint += ` ON UPDATE ${(0, _atscript_db_sql_tools.refActionToSql)(fk.onUpdate)}`;
@@ -452,23 +455,28 @@ function buildCreateTable(table, fields, foreignKeys, options) {
452
455
  /**
453
456
  * Translates a uniqu filter expression into a parameterized SQL WHERE clause.
454
457
  *
458
+ * Relational predicates (`$some` / `$none`) render as correlated `EXISTS`
459
+ * subqueries referencing the outer table by `opts.qualifier` (default: the
460
+ * source table name) — a statement with an aliased FROM must pass its alias.
461
+ *
462
+ * @param opts - since 0.1.147
455
463
  * @returns `{ sql, params }` — the WHERE clause (without "WHERE") and bound params.
456
464
  * Returns `{ sql: '1=1', params: [] }` for empty/null filters.
457
465
  */
458
- function buildWhere(filter) {
459
- return (0, _atscript_db_sql_tools.buildWhere)(sqliteDialect, filter);
466
+ function buildWhere(filter, opts) {
467
+ return (0, _atscript_db_sql_tools.buildWhere)(sqliteDialect, filter, opts);
460
468
  }
461
469
  /**
462
470
  * Like {@link buildWhere} but prefixes all column references with a table alias.
463
471
  * Produces `alias."col"` instead of `"col"` — needed for JOINed queries (e.g. FTS5 search).
472
+ * Relational predicates correlate to the same alias (since 0.1.147); their
473
+ * own subquery aliases stay unprefixed.
464
474
  */
465
475
  function buildPrefixedWhere(alias, filter) {
466
- return (0, _atscript_db_sql_tools.buildWhere)({
467
- ...sqliteDialect,
468
- quoteIdentifier(name) {
469
- return `${alias}."${esc(name)}"`;
470
- }
471
- }, filter);
476
+ return (0, _atscript_db_sql_tools.buildWhere)(sqliteDialect, filter, {
477
+ columnRef: (name) => `${alias}."${esc(name)}"`,
478
+ qualifier: alias
479
+ });
472
480
  }
473
481
  //#endregion
474
482
  //#region src/tx-gate.ts
@@ -710,6 +718,10 @@ var SqliteAdapter = class SqliteAdapter extends _atscript_db.BaseDbAdapter {
710
718
  aggregateFns() {
711
719
  return _atscript_db.ALL_AGGREGATE_FNS;
712
720
  }
721
+ /** Computed view columns and first-row joins. */
722
+ viewCapabilities() {
723
+ return _atscript_db.ALL_VIEW_CAPABILITIES;
724
+ }
713
725
  /** Whether the SQLite connection has the sqlite-vec extension loaded. */
714
726
  _supportsVector;
715
727
  /** Whether SQLite math functions (radians/asin/...) are available — geo search. */
@@ -865,6 +877,15 @@ var SqliteAdapter = class SqliteAdapter extends _atscript_db.BaseDbAdapter {
865
877
  resolveTableName() {
866
878
  return super.resolveTableName(false);
867
879
  }
880
+ /**
881
+ * Relational predicates (`$some` / `$none`) render as correlated
882
+ * `[NOT] EXISTS` subqueries — in reads and in mutation filters alike.
883
+ *
884
+ * @since 0.1.147
885
+ */
886
+ supportsRelationFilters(_mode) {
887
+ return true;
888
+ }
868
889
  /** SQLite enforces FK constraints natively via PRAGMA foreign_keys. */
869
890
  supportsNativeForeignKeys() {
870
891
  return true;
@@ -935,6 +956,16 @@ var SqliteAdapter = class SqliteAdapter extends _atscript_db.BaseDbAdapter {
935
956
  this._log(sql, params);
936
957
  return this._stmt(() => this.driver.all(sql, params));
937
958
  }
959
+ /**
960
+ * `$skip` / `$limit` per partition in one statement: a `ROW_NUMBER()`
961
+ * window over `partitionBy` (the generic `$with` loader's per-parent page).
962
+ */
963
+ async findManyPerPartition(query, partitionBy) {
964
+ const where = buildWhere(query.filter);
965
+ const { sql, params } = (0, _atscript_db_sql_tools.buildPartitionedSelect)(sqliteDialect, this.resolveTableName(), where, query.controls, partitionBy);
966
+ this._log(sql, params);
967
+ return (0, _atscript_db_sql_tools.stripPartitionRowNumber)(await this._stmt(() => this.driver.all(sql, params)));
968
+ }
938
969
  async count(query) {
939
970
  const where = buildWhere(query.filter);
940
971
  const sql = `SELECT COUNT(*) as cnt FROM "${esc(this.resolveTableName())}" WHERE ${where.sql}`;
@@ -1658,7 +1689,7 @@ var SqliteAdapter = class SqliteAdapter extends _atscript_db.BaseDbAdapter {
1658
1689
  const controls = query.controls ?? {};
1659
1690
  return {
1660
1691
  tableName: this.resolveTableName(),
1661
- where: buildWhere(query.filter),
1692
+ where: buildWhere(query.filter, { qualifier: sqliteDialect.quoteTable(_atscript_db_sql_tools.SEARCH_SOURCE_ALIAS) }),
1662
1693
  dist: haversineDistanceExpr(`"${esc(column)}"`, point),
1663
1694
  window: (0, _atscript_db_sql_tools.geoWindowFromControls)(controls),
1664
1695
  controls
package/dist/index.d.cts CHANGED
@@ -1,7 +1,7 @@
1
- import { AggregateFn, BaseDbAdapter, BucketUnit, DbQuery, DbSpace, FilterExpr, TColumnDiff, TDbDeleteResult, TDbFieldMeta, TDbInsertManyResult, TDbInsertResult, TDbObjectKind, TDbUpdateResult, TEnsureTableOptions, TExistingColumn, TFieldOps, TGenericLogger, TReferencingForeignKey, TSearchIndexInfo, TSyncColumnResult, TValueFormatterPair } from "@atscript/db";
1
+ import { AggregateFn, BaseDbAdapter, BucketUnit, DbQuery, DbSpace, FilterExpr, TColumnDiff, TDbDeleteResult, TDbFieldMeta, TDbInsertManyResult, TDbInsertResult, TDbObjectKind, TDbUpdateResult, TEnsureTableOptions, TExistingColumn, TFieldOps, TGenericLogger, TReferencingForeignKey, TSearchIndexInfo, TSyncColumnResult, TValueFormatterPair, TViewCapability } from "@atscript/db";
2
2
  import { TMetadataMap } from "@atscript/typescript/utils";
3
3
  import { FilterExpr as FilterExpr$1 } from "@uniqu/core";
4
- import { TSqlFragment, TSqlFragment as TSqlFragment$1 } from "@atscript/db-sql-tools";
4
+ import { TFilterVisitorOptions, TSqlFragment, TSqlFragment as TSqlFragment$1 } from "@atscript/db-sql-tools";
5
5
 
6
6
  //#region src/types.d.ts
7
7
  /**
@@ -269,6 +269,8 @@ declare class SqliteAdapter extends BaseDbAdapter {
269
269
  calendarBucketUnits(): ReadonlySet<BucketUnit>;
270
270
  /** Every aggregate function, `countDistinct` included. */
271
271
  aggregateFns(): ReadonlySet<AggregateFn>;
272
+ /** Computed view columns and first-row joins. */
273
+ viewCapabilities(): ReadonlySet<TViewCapability>;
272
274
  /** Whether the SQLite connection has the sqlite-vec extension loaded. */
273
275
  private _supportsVector;
274
276
  /** Whether SQLite math functions (radians/asin/...) are available — geo search. */
@@ -319,6 +321,13 @@ declare class SqliteAdapter extends BaseDbAdapter {
319
321
  protected _rollbackTransaction(state: unknown): Promise<void>;
320
322
  /** SQLite does not use schemas — override to always exclude schema. */
321
323
  resolveTableName(): string;
324
+ /**
325
+ * Relational predicates (`$some` / `$none`) render as correlated
326
+ * `[NOT] EXISTS` subqueries — in reads and in mutation filters alike.
327
+ *
328
+ * @since 0.1.147
329
+ */
330
+ supportsRelationFilters(_mode: "read" | "write"): boolean;
322
331
  /** SQLite enforces FK constraints natively via PRAGMA foreign_keys. */
323
332
  supportsNativeForeignKeys(): boolean;
324
333
  prepareId(id: unknown, _fieldType: unknown): unknown;
@@ -331,6 +340,11 @@ declare class SqliteAdapter extends BaseDbAdapter {
331
340
  insertMany(data: Array<Record<string, unknown>>): Promise<TDbInsertManyResult>;
332
341
  findOne(query: DbQuery): Promise<Record<string, unknown> | null>;
333
342
  findMany(query: DbQuery): Promise<Array<Record<string, unknown>>>;
343
+ /**
344
+ * `$skip` / `$limit` per partition in one statement: a `ROW_NUMBER()`
345
+ * window over `partitionBy` (the generic `$with` loader's per-parent page).
346
+ */
347
+ findManyPerPartition(query: DbQuery, partitionBy: readonly string[]): Promise<Array<Record<string, unknown>>>;
334
348
  count(query: DbQuery): Promise<number>;
335
349
  aggregate(query: DbQuery): Promise<Array<Record<string, unknown>>>;
336
350
  updateOne(filter: FilterExpr, data: Record<string, unknown>, ops?: TFieldOps, expectedVersion?: number): Promise<TDbUpdateResult>;
@@ -488,10 +502,15 @@ declare class SqliteAdapter extends BaseDbAdapter {
488
502
  /**
489
503
  * Translates a uniqu filter expression into a parameterized SQL WHERE clause.
490
504
  *
505
+ * Relational predicates (`$some` / `$none`) render as correlated `EXISTS`
506
+ * subqueries referencing the outer table by `opts.qualifier` (default: the
507
+ * source table name) — a statement with an aliased FROM must pass its alias.
508
+ *
509
+ * @param opts - since 0.1.147
491
510
  * @returns `{ sql, params }` — the WHERE clause (without "WHERE") and bound params.
492
511
  * Returns `{ sql: '1=1', params: [] }` for empty/null filters.
493
512
  */
494
- declare function buildWhere(filter: FilterExpr$1): TSqlFragment$1;
513
+ declare function buildWhere(filter: FilterExpr$1, opts?: TFilterVisitorOptions): TSqlFragment$1;
495
514
  //#endregion
496
515
  //#region src/index.d.ts
497
516
  /** `createAdapter` options: driver options plus the transaction-gate options (since 0.1.128). */
package/dist/index.d.mts CHANGED
@@ -1,5 +1,5 @@
1
- import { AggregateFn, BaseDbAdapter, BucketUnit, DbQuery, DbSpace, FilterExpr, TColumnDiff, TDbDeleteResult, TDbFieldMeta, TDbInsertManyResult, TDbInsertResult, TDbObjectKind, TDbUpdateResult, TEnsureTableOptions, TExistingColumn, TFieldOps, TGenericLogger, TReferencingForeignKey, TSearchIndexInfo, TSyncColumnResult, TValueFormatterPair } from "@atscript/db";
2
- import { TSqlFragment, TSqlFragment as TSqlFragment$1 } from "@atscript/db-sql-tools";
1
+ import { AggregateFn, BaseDbAdapter, BucketUnit, DbQuery, DbSpace, FilterExpr, TColumnDiff, TDbDeleteResult, TDbFieldMeta, TDbInsertManyResult, TDbInsertResult, TDbObjectKind, TDbUpdateResult, TEnsureTableOptions, TExistingColumn, TFieldOps, TGenericLogger, TReferencingForeignKey, TSearchIndexInfo, TSyncColumnResult, TValueFormatterPair, TViewCapability } from "@atscript/db";
2
+ import { TFilterVisitorOptions, TSqlFragment, TSqlFragment as TSqlFragment$1 } from "@atscript/db-sql-tools";
3
3
  import { FilterExpr as FilterExpr$1 } from "@uniqu/core";
4
4
  import { TMetadataMap } from "@atscript/typescript/utils";
5
5
 
@@ -269,6 +269,8 @@ declare class SqliteAdapter extends BaseDbAdapter {
269
269
  calendarBucketUnits(): ReadonlySet<BucketUnit>;
270
270
  /** Every aggregate function, `countDistinct` included. */
271
271
  aggregateFns(): ReadonlySet<AggregateFn>;
272
+ /** Computed view columns and first-row joins. */
273
+ viewCapabilities(): ReadonlySet<TViewCapability>;
272
274
  /** Whether the SQLite connection has the sqlite-vec extension loaded. */
273
275
  private _supportsVector;
274
276
  /** Whether SQLite math functions (radians/asin/...) are available — geo search. */
@@ -319,6 +321,13 @@ declare class SqliteAdapter extends BaseDbAdapter {
319
321
  protected _rollbackTransaction(state: unknown): Promise<void>;
320
322
  /** SQLite does not use schemas — override to always exclude schema. */
321
323
  resolveTableName(): string;
324
+ /**
325
+ * Relational predicates (`$some` / `$none`) render as correlated
326
+ * `[NOT] EXISTS` subqueries — in reads and in mutation filters alike.
327
+ *
328
+ * @since 0.1.147
329
+ */
330
+ supportsRelationFilters(_mode: "read" | "write"): boolean;
322
331
  /** SQLite enforces FK constraints natively via PRAGMA foreign_keys. */
323
332
  supportsNativeForeignKeys(): boolean;
324
333
  prepareId(id: unknown, _fieldType: unknown): unknown;
@@ -331,6 +340,11 @@ declare class SqliteAdapter extends BaseDbAdapter {
331
340
  insertMany(data: Array<Record<string, unknown>>): Promise<TDbInsertManyResult>;
332
341
  findOne(query: DbQuery): Promise<Record<string, unknown> | null>;
333
342
  findMany(query: DbQuery): Promise<Array<Record<string, unknown>>>;
343
+ /**
344
+ * `$skip` / `$limit` per partition in one statement: a `ROW_NUMBER()`
345
+ * window over `partitionBy` (the generic `$with` loader's per-parent page).
346
+ */
347
+ findManyPerPartition(query: DbQuery, partitionBy: readonly string[]): Promise<Array<Record<string, unknown>>>;
334
348
  count(query: DbQuery): Promise<number>;
335
349
  aggregate(query: DbQuery): Promise<Array<Record<string, unknown>>>;
336
350
  updateOne(filter: FilterExpr, data: Record<string, unknown>, ops?: TFieldOps, expectedVersion?: number): Promise<TDbUpdateResult>;
@@ -488,10 +502,15 @@ declare class SqliteAdapter extends BaseDbAdapter {
488
502
  /**
489
503
  * Translates a uniqu filter expression into a parameterized SQL WHERE clause.
490
504
  *
505
+ * Relational predicates (`$some` / `$none`) render as correlated `EXISTS`
506
+ * subqueries referencing the outer table by `opts.qualifier` (default: the
507
+ * source table name) — a statement with an aliased FROM must pass its alias.
508
+ *
509
+ * @param opts - since 0.1.147
491
510
  * @returns `{ sql, params }` — the WHERE clause (without "WHERE") and bound params.
492
511
  * Returns `{ sql: '1=1', params: [] }` for empty/null filters.
493
512
  */
494
- declare function buildWhere(filter: FilterExpr$1): TSqlFragment$1;
513
+ declare function buildWhere(filter: FilterExpr$1, opts?: TFilterVisitorOptions): TSqlFragment$1;
495
514
  //#endregion
496
515
  //#region src/index.d.ts
497
516
  /** `createAdapter` options: driver options plus the transaction-gate options (since 0.1.128). */
package/dist/index.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import { createRequire } from "node:module";
2
- import { ALL_AGGREGATE_FNS, ALL_BUCKET_UNITS, BaseDbAdapter, DbError, DbSpace, searchIndexNotFoundMessage, vectorIndexNotFoundMessage } from "@atscript/db";
2
+ import { ALL_AGGREGATE_FNS, ALL_BUCKET_UNITS, ALL_VIEW_CAPABILITIES, BaseDbAdapter, DbError, DbSpace, fkColumns, searchIndexNotFoundMessage, vectorIndexNotFoundMessage } from "@atscript/db";
3
3
  import { resolveAggregateSearch } from "@atscript/db/agg";
4
- import { EMPTY_AND, buildAggregateCount, buildAggregateSelect, buildCreateView, buildDelete, buildGeoSearchCount, buildGeoSearchSelect, buildInsert, buildSelect, buildUpdate, buildVectorSearchCount, buildVectorSearchSelect, buildWhere as buildWhere$1, defaultValueForType, defaultValueToSqlLiteral, derivedColumnExpr, fillReplacePayload, geoWindowFromControls, jsonDollarPath, parseRegexString, refActionToSql, renameGeoDistance, replaceColumnsFor, sqlTimeZoneLiteral, toSqlValue } from "@atscript/db-sql-tools";
4
+ import { EMPTY_AND, SEARCH_SOURCE_ALIAS, buildAggregateCount, buildAggregateSelect, buildCreateView, buildDelete, buildGeoSearchCount, buildGeoSearchSelect, buildInsert, buildPartitionedSelect, buildSelect, buildUpdate, buildVectorSearchCount, buildVectorSearchSelect, buildWhere as buildWhere$1, defaultValueForType, defaultValueToSqlLiteral, derivedColumnExpr, fillReplacePayload, geoWindowFromControls, jsonDollarPath, parseRegexString, refActionToSql, renameGeoDistance, replaceColumnsFor, sqlTimeZoneLiteral, stripPartitionRowNumber, toSqlValue } from "@atscript/db-sql-tools";
5
5
  import { bucketer } from "@uniqu/core";
6
6
  import { AsyncLocalStorage } from "node:async_hooks";
7
7
  //#region src/better-sqlite3-driver.ts
@@ -85,7 +85,8 @@ var BetterSqlite3Driver = class {
85
85
  //#region src/calendar-bucket.ts
86
86
  /**
87
87
  * Name of the scalar SQL function the adapter registers on its driver:
88
- * `atscript_bucket(value, unit, tz, weekStart)` → TEXT `'YYYY-MM-DD'` or NULL.
88
+ * `atscript_bucket(value, unit, tz, weekStart)` → TEXT `'YYYY-MM-DD'`
89
+ * (`'YYYY-MM-DDTHH:00'` for unit `hour`) or NULL.
89
90
  */
90
91
  const SQLITE_BUCKET_FN = "atscript_bucket";
91
92
  /**
@@ -286,6 +287,7 @@ const sqliteDialect = {
286
287
  },
287
288
  calendarBucket: sqliteCalendarBucket,
288
289
  jsonExtract: sqliteJsonExtract,
290
+ castDouble: (expr) => `CAST(${expr} AS REAL)`,
289
291
  createViewPrefix: "CREATE VIEW IF NOT EXISTS"
290
292
  };
291
293
  /**
@@ -437,8 +439,9 @@ function buildCreateTable(table, fields, foreignKeys, options) {
437
439
  colDefs.push(`PRIMARY KEY (${pkCols})`);
438
440
  }
439
441
  if (foreignKeys) for (const fk of foreignKeys.values()) {
440
- const localCols = fk.fields.map((f) => `"${esc(f)}"`).join(", ");
441
- const targetCols = fk.targetFields.map((f) => `"${esc(f)}"`).join(", ");
442
+ const { fields, targetFields } = fkColumns(fk);
443
+ const localCols = fields.map((f) => `"${esc(f)}"`).join(", ");
444
+ const targetCols = targetFields.map((f) => `"${esc(f)}"`).join(", ");
442
445
  let constraint = `FOREIGN KEY (${localCols}) REFERENCES "${esc(fk.targetTable)}" (${targetCols})`;
443
446
  if (fk.onDelete) constraint += ` ON DELETE ${refActionToSql(fk.onDelete)}`;
444
447
  if (fk.onUpdate) constraint += ` ON UPDATE ${refActionToSql(fk.onUpdate)}`;
@@ -451,23 +454,28 @@ function buildCreateTable(table, fields, foreignKeys, options) {
451
454
  /**
452
455
  * Translates a uniqu filter expression into a parameterized SQL WHERE clause.
453
456
  *
457
+ * Relational predicates (`$some` / `$none`) render as correlated `EXISTS`
458
+ * subqueries referencing the outer table by `opts.qualifier` (default: the
459
+ * source table name) — a statement with an aliased FROM must pass its alias.
460
+ *
461
+ * @param opts - since 0.1.147
454
462
  * @returns `{ sql, params }` — the WHERE clause (without "WHERE") and bound params.
455
463
  * Returns `{ sql: '1=1', params: [] }` for empty/null filters.
456
464
  */
457
- function buildWhere(filter) {
458
- return buildWhere$1(sqliteDialect, filter);
465
+ function buildWhere(filter, opts) {
466
+ return buildWhere$1(sqliteDialect, filter, opts);
459
467
  }
460
468
  /**
461
469
  * Like {@link buildWhere} but prefixes all column references with a table alias.
462
470
  * Produces `alias."col"` instead of `"col"` — needed for JOINed queries (e.g. FTS5 search).
471
+ * Relational predicates correlate to the same alias (since 0.1.147); their
472
+ * own subquery aliases stay unprefixed.
463
473
  */
464
474
  function buildPrefixedWhere(alias, filter) {
465
- return buildWhere$1({
466
- ...sqliteDialect,
467
- quoteIdentifier(name) {
468
- return `${alias}."${esc(name)}"`;
469
- }
470
- }, filter);
475
+ return buildWhere$1(sqliteDialect, filter, {
476
+ columnRef: (name) => `${alias}."${esc(name)}"`,
477
+ qualifier: alias
478
+ });
471
479
  }
472
480
  //#endregion
473
481
  //#region src/tx-gate.ts
@@ -709,6 +717,10 @@ var SqliteAdapter = class SqliteAdapter extends BaseDbAdapter {
709
717
  aggregateFns() {
710
718
  return ALL_AGGREGATE_FNS;
711
719
  }
720
+ /** Computed view columns and first-row joins. */
721
+ viewCapabilities() {
722
+ return ALL_VIEW_CAPABILITIES;
723
+ }
712
724
  /** Whether the SQLite connection has the sqlite-vec extension loaded. */
713
725
  _supportsVector;
714
726
  /** Whether SQLite math functions (radians/asin/...) are available — geo search. */
@@ -864,6 +876,15 @@ var SqliteAdapter = class SqliteAdapter extends BaseDbAdapter {
864
876
  resolveTableName() {
865
877
  return super.resolveTableName(false);
866
878
  }
879
+ /**
880
+ * Relational predicates (`$some` / `$none`) render as correlated
881
+ * `[NOT] EXISTS` subqueries — in reads and in mutation filters alike.
882
+ *
883
+ * @since 0.1.147
884
+ */
885
+ supportsRelationFilters(_mode) {
886
+ return true;
887
+ }
867
888
  /** SQLite enforces FK constraints natively via PRAGMA foreign_keys. */
868
889
  supportsNativeForeignKeys() {
869
890
  return true;
@@ -934,6 +955,16 @@ var SqliteAdapter = class SqliteAdapter extends BaseDbAdapter {
934
955
  this._log(sql, params);
935
956
  return this._stmt(() => this.driver.all(sql, params));
936
957
  }
958
+ /**
959
+ * `$skip` / `$limit` per partition in one statement: a `ROW_NUMBER()`
960
+ * window over `partitionBy` (the generic `$with` loader's per-parent page).
961
+ */
962
+ async findManyPerPartition(query, partitionBy) {
963
+ const where = buildWhere(query.filter);
964
+ const { sql, params } = buildPartitionedSelect(sqliteDialect, this.resolveTableName(), where, query.controls, partitionBy);
965
+ this._log(sql, params);
966
+ return stripPartitionRowNumber(await this._stmt(() => this.driver.all(sql, params)));
967
+ }
937
968
  async count(query) {
938
969
  const where = buildWhere(query.filter);
939
970
  const sql = `SELECT COUNT(*) as cnt FROM "${esc(this.resolveTableName())}" WHERE ${where.sql}`;
@@ -1657,7 +1688,7 @@ var SqliteAdapter = class SqliteAdapter extends BaseDbAdapter {
1657
1688
  const controls = query.controls ?? {};
1658
1689
  return {
1659
1690
  tableName: this.resolveTableName(),
1660
- where: buildWhere(query.filter),
1691
+ where: buildWhere(query.filter, { qualifier: sqliteDialect.quoteTable(SEARCH_SOURCE_ALIAS) }),
1661
1692
  dist: haversineDistanceExpr(`"${esc(column)}"`, point),
1662
1693
  window: geoWindowFromControls(controls),
1663
1694
  controls
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atscript/db-sqlite",
3
- "version": "0.1.145",
3
+ "version": "0.1.147",
4
4
  "description": "SQLite adapter for @atscript/db with swappable driver support.",
5
5
  "keywords": [
6
6
  "atscript",
@@ -36,21 +36,21 @@
36
36
  "access": "public"
37
37
  },
38
38
  "devDependencies": {
39
- "@atscript/core": "^0.1.97",
40
- "@atscript/typescript": "^0.1.97",
39
+ "@atscript/core": "^0.1.99",
40
+ "@atscript/typescript": "^0.1.99",
41
41
  "@types/better-sqlite3": "^7.6.13",
42
- "@uniqu/core": "^0.1.11",
42
+ "@uniqu/core": "^0.1.12",
43
43
  "better-sqlite3": "^12.6.2",
44
44
  "sqlite-vec": "^0.1.9",
45
- "unplugin-atscript": "^0.1.97"
45
+ "unplugin-atscript": "^0.1.99"
46
46
  },
47
47
  "peerDependencies": {
48
- "@atscript/core": "^0.1.97",
49
- "@atscript/typescript": "^0.1.97",
50
- "@uniqu/core": "^0.1.11",
48
+ "@atscript/core": "^0.1.99",
49
+ "@atscript/typescript": "^0.1.99",
50
+ "@uniqu/core": "^0.1.12",
51
51
  "better-sqlite3": ">=11.0.0",
52
- "@atscript/db": "^0.1.145",
53
- "@atscript/db-sql-tools": "^0.1.145"
52
+ "@atscript/db": "^0.1.147",
53
+ "@atscript/db-sql-tools": "^0.1.147"
54
54
  },
55
55
  "peerDependenciesMeta": {
56
56
  "better-sqlite3": {