@sixb/sqlite 0.1.15 → 0.1.16

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.js CHANGED
@@ -10567,7 +10567,7 @@ var PAGE_TOKEN_PREFIX = "keyset:";
10567
10567
  var DEFAULT_EXPANSION_FANOUT = 1000;
10568
10568
  function compileObjectQuery(projectId, query, options = {}) {
10569
10569
  if (hasVectorProfile(query) && !isVectorProfileQuery(query)) {
10570
- throw new ObjectQueryExecutionError("unsupported_vector_composition", "Vector search supports one profile with filters before ranking and limit/project after.");
10570
+ throw new ObjectQueryExecutionError("unsupported_vector_composition", "Vector search supports one profile with filters, traversals or sets before ranking and limit/project after.");
10571
10571
  }
10572
10572
  const source = options.source ?? DEFAULT_OBJECT_QUERY_SOURCE;
10573
10573
  const ctx = { probeLimit: options.includeTotal === false, source };
@@ -10640,9 +10640,29 @@ function compileVector(projectId, query, ctx) {
10640
10640
  { kind: "column", column: "_vector_score", direction: "desc" },
10641
10641
  ...identityOrderFields().map((field) => ({ ...field, binary: true }))
10642
10642
  ]);
10643
- const sql = `SELECT * FROM (SELECT input.*, max(-1, min(1, 1 - vec_distance_cosine(vectors.embedding, ?))) AS _vector_score
10644
- ${candidates}) AS ranked ORDER BY ${order.sql} LIMIT ?`;
10645
- const args = [encodeSqliteVector(values), ...candidateArgs, query.k];
10643
+ const rankedOrder = compileOrder(order.fields, "ranked");
10644
+ const sql = `SELECT stored.project_id, stored.object_type_id, stored.primary_id,
10645
+ stored.properties, stored.properties AS _cursor_properties,
10646
+ stored.created_at, stored.updated_at, stored.version, stored.last_commit_id,
10647
+ ranked._vector_candidate_count, ranked._vector_score
10648
+ FROM (
10649
+ WITH _sixb_vector_candidates AS MATERIALIZED (
10650
+ SELECT input.project_id, input.object_type_id, input.primary_id,
10651
+ vectors.embedding AS _vector_embedding ${candidates} LIMIT ?
10652
+ ), _sixb_vector_budget AS (
10653
+ SELECT COUNT(*) AS _vector_candidate_count FROM _sixb_vector_candidates
10654
+ )
10655
+ SELECT input.project_id, input.object_type_id, input.primary_id, budget._vector_candidate_count,
10656
+ CASE WHEN budget._vector_candidate_count <= ?
10657
+ THEN max(-1, min(1, 1 - vec_distance_cosine(input._vector_embedding, ?)))
10658
+ END AS _vector_score
10659
+ FROM _sixb_vector_candidates AS input CROSS JOIN _sixb_vector_budget AS budget
10660
+ ORDER BY ${order.sql} LIMIT ?
10661
+ ) AS ranked CROSS JOIN ${ctx.source.objectsTable} AS stored
10662
+ ON stored.project_id = ranked.project_id AND stored.object_type_id = ranked.object_type_id
10663
+ AND stored.primary_id = ranked.primary_id
10664
+ ORDER BY ${rankedOrder.sql}`;
10665
+ const args = [...candidateArgs, limit + 1, limit, encodeSqliteVector(values), query.k];
10646
10666
  return {
10647
10667
  sql,
10648
10668
  args,
@@ -10652,7 +10672,9 @@ function compileVector(projectId, query, ctx) {
10652
10672
  vectorProbe: {
10653
10673
  sql: `SELECT COUNT(*) AS total FROM (SELECT 1 ${candidates} LIMIT ?) AS candidates`,
10654
10674
  args: [...candidateArgs, limit + 1],
10655
- limit
10675
+ limit,
10676
+ rowLimit: query.k,
10677
+ totalLimit: query.k
10656
10678
  },
10657
10679
  hasMore: () => false,
10658
10680
  trimRows: identityRows,
@@ -10811,7 +10833,11 @@ function compileLimit(projectId, inputQuery, rawLimit, ctx) {
10811
10833
  FROM (${input.sql}) AS input
10812
10834
  `,
10813
10835
  totalArgs: input.args,
10814
- vectorProbe: input.vectorProbe,
10836
+ vectorProbe: input.vectorProbe ? {
10837
+ ...input.vectorProbe,
10838
+ rowLimit: Math.min(input.vectorProbe.rowLimit, rowLimit),
10839
+ totalLimit: input.vectorProbe.rowLimit
10840
+ } : undefined,
10815
10841
  order: input.order,
10816
10842
  hasMore: (rowCount, total) => total === undefined ? ctx.probeLimit && rowCount > limit : limit < total,
10817
10843
  trimRows: ctx.probeLimit ? (rows) => rows.slice(0, limit) : identityRows,
@@ -11088,7 +11114,7 @@ function compileProject(projectId, inputQuery, properties, ctx) {
11088
11114
  input.created_at,
11089
11115
  input.updated_at,
11090
11116
  input.version,
11091
- input.last_commit_id${input.vectorProbe ? ", input._vector_score" : ""}
11117
+ input.last_commit_id${input.vectorProbe ? ", input._vector_score, input._vector_candidate_count" : ""}
11092
11118
  FROM (${input.sql}) AS input
11093
11119
  ORDER BY ${inputOrder.sql}
11094
11120
  `,
@@ -11632,19 +11658,20 @@ class SqliteObjectReader {
11632
11658
  ensureSqliteVectorSearch(this.db);
11633
11659
  const probe = compiled.vectorProbe;
11634
11660
  const row = this.db.query(probe.sql).get(...probe.args);
11635
- if (Number(row?.total ?? 0) > probe.limit) {
11636
- throw new ObjectQueryExecutionError3("vector_work_limit_exceeded", `Exact vector search supports at most ${probe.limit} eligible vectors at this dimension. Narrow the query filters.`);
11637
- }
11661
+ assertVectorCandidateCount(row?.total, probe.limit);
11638
11662
  }
11639
11663
  queryObjects(params) {
11640
- this.assertVectorSearch(params);
11641
11664
  const source = this.source;
11642
11665
  const compiled = compileObjectQuery(params.projectId, params.query, {
11643
11666
  includeTotal: params.includeTotal,
11644
11667
  source
11645
11668
  });
11646
- const total = params.includeTotal === false ? undefined : readTotal(this.db, compiled);
11669
+ if (compiled.vectorProbe)
11670
+ ensureSqliteVectorSearch(this.db);
11671
+ const ordinaryTotal = params.includeTotal === false || compiled.vectorProbe ? undefined : readTotal(this.db, compiled);
11647
11672
  const rawRows = this.db.query(compiled.sql).all(...compiled.args);
11673
+ const vectorTotal = this.vectorResultTotal(compiled, rawRows);
11674
+ const total = params.includeTotal === false ? undefined : vectorTotal ?? ordinaryTotal;
11648
11675
  const rows = compiled.trimRows(rawRows);
11649
11676
  const hasMore = total === undefined && compiled.hasMoreProbe ? compiled.hasMoreProbe.hasMore(this.db.query(compiled.hasMoreProbe.sql).all(...compiled.hasMoreProbe.args).length) : compiled.hasMore(rawRows.length, total);
11650
11677
  return {
@@ -11654,6 +11681,17 @@ class SqliteObjectReader {
11654
11681
  ...total === undefined ? {} : { total }
11655
11682
  };
11656
11683
  }
11684
+ vectorResultTotal(compiled, rows) {
11685
+ const probe = compiled.vectorProbe;
11686
+ if (!probe)
11687
+ return;
11688
+ let count = rows[0]?._vector_candidate_count;
11689
+ if (rows.length === 0) {
11690
+ count = probe.rowLimit === 0 ? this.db.query(probe.sql).get(...probe.args)?.total : 0;
11691
+ }
11692
+ assertVectorCandidateCount(count, probe.limit);
11693
+ return Math.min(count, probe.totalLimit);
11694
+ }
11657
11695
  countObjects(params) {
11658
11696
  this.assertVectorSearch(params);
11659
11697
  const source = this.source;
@@ -11967,6 +12005,14 @@ function sqliteFacetValue(valueType, value) {
11967
12005
  }
11968
12006
  return value;
11969
12007
  }
12008
+ function assertVectorCandidateCount(count, limit) {
12009
+ if (typeof count !== "number" || !Number.isSafeInteger(count) || count < 0) {
12010
+ throw new ObjectQueryExecutionError3("invalid_vector_candidate_count", "Storage did not return a valid vector candidate count.");
12011
+ }
12012
+ if (count > limit) {
12013
+ throw new ObjectQueryExecutionError3("vector_work_limit_exceeded", `Exact vector search supports at most ${limit} eligible vectors at this dimension. Narrow the query filters.`);
12014
+ }
12015
+ }
11970
12016
  function existsProbeQuery(query) {
11971
12017
  return { kind: "limit", limit: 1, input: stripOuterRowShape(query) };
11972
12018
  }
@@ -12058,7 +12104,7 @@ function compileSelectedReadScopeCte(scopeJson, projectId) {
12058
12104
  _sixb_scope_root_facts(project_id, root_id, node_id, object_type_id, primary_id) AS (
12059
12105
  SELECT anchor.project_id, root.root_id, root.node_id, root.object_type_id, root.primary_id
12060
12106
  FROM _sixb_scope_roots AS root
12061
- JOIN objects AS anchor
12107
+ CROSS JOIN objects AS anchor
12062
12108
  ON anchor.project_id = ?
12063
12109
  AND anchor.object_type_id = root.object_type_id
12064
12110
  AND anchor.primary_id = root.primary_id
@@ -12140,7 +12186,7 @@ function compileSelectedReadScopeCte(scopeJson, projectId) {
12140
12186
  GROUP BY reachable.project_id, reachable.object_type_id, reachable.primary_id
12141
12187
  ),
12142
12188
  _sixb_scope_objects AS (
12143
- SELECT stored.project_id, stored.object_type_id, stored.primary_id,
12189
+ SELECT grants.project_id, grants.object_type_id, grants.primary_id,
12144
12190
  COALESCE((
12145
12191
  SELECT json_group_object(property.key, ${sqliteJsonEachValue("property")})
12146
12192
  FROM json_each(stored.properties) AS property
@@ -12230,12 +12276,12 @@ function compileSelectedReadScopeCte(scopeJson, projectId) {
12230
12276
  ),
12231
12277
  _sixb_scope_links AS (
12232
12278
  SELECT
12233
- stored.project_id,
12234
- stored.source_type_id,
12235
- stored.source_id,
12236
- stored.link_id,
12237
- stored.target_type_id,
12238
- stored.target_id,
12279
+ visible.project_id,
12280
+ visible.source_type_id,
12281
+ visible.source_id,
12282
+ visible.link_id,
12283
+ visible.target_type_id,
12284
+ visible.target_id,
12239
12285
  CASE
12240
12286
  WHEN stored.properties IS NULL THEN NULL
12241
12287
  ELSE NULLIF(
@@ -18377,4 +18423,4 @@ export {
18377
18423
  migrateSqliteStorage
18378
18424
  };
18379
18425
 
18380
- //# debugId=1D3AEE45CA656B6464756E2164756E21
18426
+ //# debugId=A2CEAFAB428734DF64756E2164756E21