@sixb/pg 0.1.6 → 0.1.8

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 (88) hide show
  1. package/dist/agents/rows.d.ts +8 -5
  2. package/dist/agents/rows.d.ts.map +1 -1
  3. package/dist/agents/runs.d.ts +3 -2
  4. package/dist/agents/runs.d.ts.map +1 -1
  5. package/dist/agents/threads.d.ts.map +1 -1
  6. package/dist/ai-cost-groups.d.ts +5 -0
  7. package/dist/ai-cost-groups.d.ts.map +1 -0
  8. package/dist/auth-storage/auth-storage.d.ts +4 -1
  9. package/dist/auth-storage/auth-storage.d.ts.map +1 -1
  10. package/dist/auth-storage/device-authorizations.d.ts +29 -0
  11. package/dist/auth-storage/device-authorizations.d.ts.map +1 -0
  12. package/dist/auth-storage/rows.d.ts +19 -1
  13. package/dist/auth-storage/rows.d.ts.map +1 -1
  14. package/dist/auth-storage/shared.d.ts +1 -1
  15. package/dist/auth-storage/shared.d.ts.map +1 -1
  16. package/dist/index.d.ts +6 -1
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/index.js +8327 -5838
  19. package/dist/index.js.map +28 -19
  20. package/dist/migrations.d.ts.map +1 -1
  21. package/dist/objects/index.d.ts +2 -0
  22. package/dist/objects/index.d.ts.map +1 -0
  23. package/dist/{pg-object-query-compiler.d.ts → objects/query-compiler.d.ts} +25 -4
  24. package/dist/objects/query-compiler.d.ts.map +1 -0
  25. package/dist/objects/read-scope.d.ts +17 -0
  26. package/dist/objects/read-scope.d.ts.map +1 -0
  27. package/dist/objects/reader.d.ts +50 -0
  28. package/dist/objects/reader.d.ts.map +1 -0
  29. package/dist/objects/rows.d.ts +47 -0
  30. package/dist/objects/rows.d.ts.map +1 -0
  31. package/dist/objects/selected-reader.d.ts +8 -0
  32. package/dist/objects/selected-reader.d.ts.map +1 -0
  33. package/dist/{pg-object-storage.d.ts → objects/storage.d.ts} +12 -20
  34. package/dist/objects/storage.d.ts.map +1 -0
  35. package/dist/pg-ai-cost-storage.d.ts +2 -1
  36. package/dist/pg-ai-cost-storage.d.ts.map +1 -1
  37. package/dist/pg-ai-limit-storage.d.ts +34 -0
  38. package/dist/pg-ai-limit-storage.d.ts.map +1 -0
  39. package/dist/pg-ai-usage-storage.d.ts +28 -0
  40. package/dist/pg-ai-usage-storage.d.ts.map +1 -1
  41. package/dist/pg-execution-storage.d.ts +3 -2
  42. package/dist/pg-execution-storage.d.ts.map +1 -1
  43. package/dist/share-grant-storage.d.ts +11 -0
  44. package/dist/share-grant-storage.d.ts.map +1 -0
  45. package/dist/share-session-storage.d.ts +11 -0
  46. package/dist/share-session-storage.d.ts.map +1 -0
  47. package/dist/storage-errors.d.ts +2 -0
  48. package/dist/storage-errors.d.ts.map +1 -1
  49. package/dist/transactions.d.ts +9 -2
  50. package/dist/transactions.d.ts.map +1 -1
  51. package/package.json +4 -4
  52. package/src/agents/rows.ts +38 -9
  53. package/src/agents/runs.ts +148 -11
  54. package/src/agents/threads.ts +1 -17
  55. package/src/ai-cost-groups.ts +102 -0
  56. package/src/auth-storage/auth-storage.ts +84 -0
  57. package/src/auth-storage/device-authorizations.ts +131 -0
  58. package/src/auth-storage/rows.ts +41 -0
  59. package/src/auth-storage/shared.ts +1 -0
  60. package/src/index.ts +24 -4
  61. package/src/migrations/029-model-accounting.sql +24 -0
  62. package/src/migrations/030-ai-usage-limits.sql +94 -0
  63. package/src/migrations/031-subagent-runs.sql +97 -0
  64. package/src/migrations/032-conversation-run-spec.sql +23 -0
  65. package/src/migrations/033-retire-agent-definitions.sql +28 -0
  66. package/src/migrations/034-device-authorizations.sql +24 -0
  67. package/src/migrations/035-share-grants.sql +57 -0
  68. package/src/migrations/036-share-sessions.sql +173 -0
  69. package/src/migrations.ts +22 -0
  70. package/src/objects/index.ts +1 -0
  71. package/src/{pg-object-query-compiler.ts → objects/query-compiler.ts} +185 -100
  72. package/src/objects/read-scope.ts +324 -0
  73. package/src/objects/reader.ts +604 -0
  74. package/src/objects/rows.ts +146 -0
  75. package/src/objects/selected-reader.ts +118 -0
  76. package/src/objects/storage.ts +305 -0
  77. package/src/pg-ai-cost-storage.ts +71 -24
  78. package/src/pg-ai-limit-storage.ts +901 -0
  79. package/src/pg-ai-usage-storage.ts +34 -0
  80. package/src/pg-execution-storage.ts +21 -2
  81. package/src/pg-workflow-run-storage.ts +8 -8
  82. package/src/share-grant-storage.ts +236 -0
  83. package/src/share-session-storage.ts +127 -0
  84. package/src/storage-errors.ts +6 -0
  85. package/src/transactions.ts +46 -5
  86. package/dist/pg-object-query-compiler.d.ts.map +0 -1
  87. package/dist/pg-object-storage.d.ts.map +0 -1
  88. package/src/pg-object-storage.ts +0 -734
@@ -45,6 +45,7 @@ interface CompiledHasMoreProbe {
45
45
 
46
46
  interface CompileContext {
47
47
  probeLimit: boolean
48
+ source: PgObjectQuerySource
48
49
  }
49
50
 
50
51
  interface CompiledPredicate {
@@ -89,7 +90,6 @@ interface EncodedCursorValue {
89
90
  }
90
91
 
91
92
  const PAGE_TOKEN_PREFIX = "keyset:"
92
- const exactContext: CompileContext = { probeLimit: false }
93
93
  // Per-parent fanout the core executor bakes into every pushed-down expansion;
94
94
  // this default only guards a malformed (un-baked) IR and mirrors the core cap.
95
95
  const DEFAULT_EXPANSION_FANOUT = 1_000
@@ -97,11 +97,15 @@ const DEFAULT_EXPANSION_FANOUT = 1_000
97
97
  export function compilePgObjectQuery(
98
98
  projectId: string,
99
99
  query: ObjectQuery,
100
- options: { includeTotal?: boolean } = {}
100
+ options: { includeTotal?: boolean; source?: PgObjectQuerySource } = {}
101
101
  ): CompiledPgObjectQuery {
102
- const compiled = compileObjectQueryInternal(projectId, query, {
103
- probeLimit: options.includeTotal === false,
104
- })
102
+ const source = options.source ?? DEFAULT_OBJECT_QUERY_SOURCE
103
+ const compiled = source.wrapQuery(
104
+ compileObjectQueryInternal(projectId, query, {
105
+ probeLimit: options.includeTotal === false,
106
+ source,
107
+ })
108
+ )
105
109
  return {
106
110
  ...compiled,
107
111
  sql: numberPlaceholders(compiled.sql),
@@ -115,44 +119,90 @@ export function compilePgObjectQuery(
115
119
  }
116
120
  }
117
121
 
122
+ /** Physical relations used by the PostgreSQL object-query compiler. */
123
+ export interface PgObjectQuerySource {
124
+ readonly objectsTable: string
125
+ readonly linksTable: string
126
+ /** Wrap a terminal SELECT without its own WITH clause; the selected source owns the only WITH. */
127
+ wrapStatement(
128
+ sql: string,
129
+ args?: readonly unknown[]
130
+ ): {
131
+ readonly sql: string
132
+ readonly args: unknown[]
133
+ }
134
+ wrapQuery(query: CompiledPgObjectQuery): CompiledPgObjectQuery
135
+ }
136
+
137
+ /** Prefix an optional query source, then assign PostgreSQL positional placeholders. */
138
+ export function compilePgObjectStatement(
139
+ sql: string,
140
+ args: readonly unknown[] = [],
141
+ source?: PgObjectQuerySource
142
+ ): CompiledPgScalarQuery {
143
+ return numberCompiledQuery((source ?? DEFAULT_OBJECT_QUERY_SOURCE).wrapStatement(sql, args))
144
+ }
145
+
146
+ export const DEFAULT_OBJECT_QUERY_SOURCE: PgObjectQuerySource = {
147
+ objectsTable: "objects",
148
+ linksTable: "links",
149
+ wrapStatement: (sql, args = []) => ({ sql, args: [...args] }),
150
+ wrapQuery: (query) => query,
151
+ }
152
+
153
+ function exactContext(ctx: CompileContext): CompileContext {
154
+ return ctx.probeLimit ? { ...ctx, probeLimit: false } : ctx
155
+ }
156
+
118
157
  export function compilePgObjectCountQuery(
119
158
  projectId: string,
120
- query: ObjectQuery
159
+ query: ObjectQuery,
160
+ options: { source?: PgObjectQuerySource } = {}
121
161
  ): CompiledPgScalarQuery {
122
- const source = compileAggregateSource(projectId, query)
123
- return numberCompiledQuery({
124
- sql: `
162
+ const querySource = options.source ?? DEFAULT_OBJECT_QUERY_SOURCE
163
+ const source = compileAggregateSource(projectId, query, querySource)
164
+ return numberCompiledQuery(
165
+ querySource.wrapStatement(
166
+ `
125
167
  SELECT COUNT(*)::bigint AS count
126
168
  FROM (${source.sql}) AS input
127
169
  `,
128
- args: source.args,
129
- })
170
+ source.args
171
+ )
172
+ )
130
173
  }
131
174
 
132
175
  export function compilePgObjectExistsQuery(
133
176
  projectId: string,
134
- query: ObjectQuery
177
+ query: ObjectQuery,
178
+ options: { source?: PgObjectQuerySource } = {}
135
179
  ): CompiledPgScalarQuery {
136
- const source = compileAggregateSource(projectId, query)
137
- return numberCompiledQuery({
138
- sql: `
180
+ const querySource = options.source ?? DEFAULT_OBJECT_QUERY_SOURCE
181
+ const source = compileAggregateSource(projectId, query, querySource)
182
+ return numberCompiledQuery(
183
+ querySource.wrapStatement(
184
+ `
139
185
  SELECT 1
140
186
  FROM (${source.sql}) AS input
141
187
  LIMIT 1
142
188
  `,
143
- args: source.args,
144
- })
189
+ source.args
190
+ )
191
+ )
145
192
  }
146
193
 
147
194
  export function compilePgObjectFacetQuery(
148
195
  projectId: string,
149
196
  query: ObjectQuery,
150
197
  propertyId: string,
151
- limit: number
198
+ limit: number,
199
+ options: { source?: PgObjectQuerySource } = {}
152
200
  ): CompiledPgFacetQuery {
153
- const source = compileAggregateSource(projectId, query)
154
- return numberCompiledQuery({
155
- sql: `
201
+ const querySource = options.source ?? DEFAULT_OBJECT_QUERY_SOURCE
202
+ const source = compileAggregateSource(projectId, query, querySource)
203
+ return numberCompiledQuery(
204
+ querySource.wrapStatement(
205
+ `
156
206
  SELECT facet.value_type, facet.value_text, COUNT(*)::bigint AS count
157
207
  FROM (
158
208
  SELECT
@@ -165,8 +215,9 @@ export function compilePgObjectFacetQuery(
165
215
  ORDER BY count DESC, facet.value_text ASC
166
216
  LIMIT ?
167
217
  `,
168
- args: [propertyId, propertyId, ...source.args, propertyId, limit],
169
- })
218
+ [propertyId, propertyId, ...source.args, propertyId, limit]
219
+ )
220
+ )
170
221
  }
171
222
 
172
223
  function compileObjectQueryInternal(
@@ -176,27 +227,28 @@ function compileObjectQueryInternal(
176
227
  ): CompiledPgObjectQuery {
177
228
  switch (query.kind) {
178
229
  case "start":
179
- return compileStart(projectId, query)
230
+ return compileStart(projectId, query, ctx)
180
231
  case "refs":
181
- return compileRefs(projectId, query)
232
+ return compileRefs(projectId, query, ctx)
182
233
  case "filter":
183
- return compileFilter(projectId, query.input, query.predicate)
234
+ return compileFilter(projectId, query.input, query.predicate, ctx)
184
235
  case "sort":
185
236
  return compileSort(projectId, query.input, query.fields, ctx)
186
237
  case "limit":
187
238
  return compileLimit(projectId, query.input, query.limit, ctx)
188
239
  case "page":
189
- return compilePage(projectId, query.input, query.pageSize, query.pageToken)
240
+ return compilePage(projectId, query.input, query.pageSize, query.pageToken, ctx)
190
241
  case "traverse":
191
242
  return compileTraversal(
192
243
  projectId,
193
244
  query.input,
194
245
  query.linkId,
195
246
  query.direction,
196
- query.sourceObjectTypeId
247
+ query.sourceObjectTypeId,
248
+ ctx
197
249
  )
198
250
  case "set":
199
- return compileSet(projectId, query.op, query.inputs)
251
+ return compileSet(projectId, query.op, query.inputs, ctx)
200
252
  case "project":
201
253
  return compileProject(projectId, query.input, query.properties, ctx)
202
254
  case "text":
@@ -205,10 +257,11 @@ function compileObjectQueryInternal(
205
257
  query.input,
206
258
  query.query,
207
259
  query.fields,
208
- query.fieldsByObjectType
260
+ query.fieldsByObjectType,
261
+ ctx
209
262
  )
210
263
  case "expand":
211
- return compileExpand(projectId, query.input, query.expansions)
264
+ return compileExpand(projectId, query.input, query.expansions, ctx)
212
265
  case "vector":
213
266
  throw new Error(
214
267
  `[SixbPg] PostgreSQL object storage does not support query node '${query.kind}'`
@@ -218,7 +271,8 @@ function compileObjectQueryInternal(
218
271
 
219
272
  function compileStart(
220
273
  projectId: string,
221
- query: Extract<ObjectQuery, { kind: "start" }>
274
+ query: Extract<ObjectQuery, { kind: "start" }>,
275
+ ctx: CompileContext
222
276
  ): CompiledPgObjectQuery {
223
277
  if (query.includeSubtypes === true) {
224
278
  throw new Error("[SixbPg] PostgreSQL object storage does not support start.includeSubtypes")
@@ -227,7 +281,7 @@ function compileStart(
227
281
  const order = compileOrder(identityOrderFields())
228
282
  const sql = `
229
283
  SELECT *, properties AS _cursor_properties
230
- FROM objects
284
+ FROM ${ctx.source.objectsTable}
231
285
  WHERE project_id = ? AND object_type_id = ?
232
286
  ORDER BY ${order.sql}
233
287
  `
@@ -235,8 +289,7 @@ function compileStart(
235
289
  return {
236
290
  sql,
237
291
  args: [projectId, query.objectTypeId, ...order.args],
238
- totalSql:
239
- "SELECT COUNT(*)::bigint AS total FROM objects WHERE project_id = ? AND object_type_id = ?",
292
+ totalSql: `SELECT COUNT(*)::bigint AS total FROM ${ctx.source.objectsTable} WHERE project_id = ? AND object_type_id = ?`,
240
293
  totalArgs: [projectId, query.objectTypeId],
241
294
  order,
242
295
  hasMore: () => false,
@@ -247,7 +300,8 @@ function compileStart(
247
300
 
248
301
  function compileRefs(
249
302
  projectId: string,
250
- query: Extract<ObjectQuery, { kind: "refs" }>
303
+ query: Extract<ObjectQuery, { kind: "refs" }>,
304
+ ctx: CompileContext
251
305
  ): CompiledPgObjectQuery {
252
306
  if (query.refs.length === 0) {
253
307
  throw new Error("[SixbPg] PostgreSQL object storage requires at least one ref")
@@ -263,10 +317,9 @@ function compileRefs(
263
317
  FROM jsonb_array_elements(?::text::jsonb) AS ref(value)
264
318
  `
265
319
  const sql = `
266
- WITH requested AS (${requested})
267
320
  SELECT selected.*, selected.properties AS _cursor_properties
268
- FROM requested
269
- JOIN objects AS selected
321
+ FROM (${requested}) AS requested
322
+ JOIN ${ctx.source.objectsTable} AS selected
270
323
  ON selected.project_id = ?
271
324
  AND selected.object_type_id = requested.object_type_id
272
325
  AND selected.primary_id = requested.primary_id
@@ -277,10 +330,9 @@ function compileRefs(
277
330
  sql,
278
331
  args: [refsJson, projectId, ...selectedOrder.args],
279
332
  totalSql: `
280
- WITH requested AS (${requested})
281
333
  SELECT COUNT(*)::bigint AS total
282
- FROM requested
283
- JOIN objects AS selected
334
+ FROM (${requested}) AS requested
335
+ JOIN ${ctx.source.objectsTable} AS selected
284
336
  ON selected.project_id = ?
285
337
  AND selected.object_type_id = requested.object_type_id
286
338
  AND selected.primary_id = requested.primary_id
@@ -296,17 +348,19 @@ function compileRefs(
296
348
  function compileFilter(
297
349
  projectId: string,
298
350
  inputQuery: ObjectQuery,
299
- predicateNode: ObjectQueryPredicate
351
+ predicateNode: ObjectQueryPredicate,
352
+ ctx: CompileContext
300
353
  ): CompiledPgObjectQuery {
301
- return compileWhere(projectId, inputQuery, compilePredicate(predicateNode))
354
+ return compileWhere(projectId, inputQuery, compilePredicate(predicateNode), ctx)
302
355
  }
303
356
 
304
357
  function compileWhere(
305
358
  projectId: string,
306
359
  inputQuery: ObjectQuery,
307
- predicate: CompiledPredicate
360
+ predicate: CompiledPredicate,
361
+ ctx: CompileContext
308
362
  ): CompiledPgObjectQuery {
309
- const input = compileObjectQueryInternal(projectId, inputQuery, exactContext)
363
+ const input = compileObjectQueryInternal(projectId, inputQuery, exactContext(ctx))
310
364
  const sql = `
311
365
  SELECT *
312
366
  FROM (${input.sql}) AS input
@@ -335,12 +389,14 @@ function compileText(
335
389
  inputQuery: ObjectQuery,
336
390
  query: string,
337
391
  fields: readonly string[] | undefined,
338
- fieldsByObjectType: Readonly<Record<string, readonly string[]>> | undefined
392
+ fieldsByObjectType: Readonly<Record<string, readonly string[]>> | undefined,
393
+ ctx: CompileContext
339
394
  ): CompiledPgObjectQuery {
340
395
  return compileWhere(
341
396
  projectId,
342
397
  inputQuery,
343
- compileTextSearchPredicate(query, fields, fieldsByObjectType)
398
+ compileTextSearchPredicate(query, fields, fieldsByObjectType),
399
+ ctx
344
400
  )
345
401
  }
346
402
 
@@ -350,7 +406,7 @@ function compileSort(
350
406
  fields: readonly ObjectQuerySortField[],
351
407
  ctx: CompileContext
352
408
  ): CompiledPgObjectQuery {
353
- const input = compileObjectQueryInternal(projectId, inputQuery, exactContext)
409
+ const input = compileObjectQueryInternal(projectId, inputQuery, exactContext(ctx))
354
410
  const probeInput =
355
411
  ctx.probeLimit && needsLimitProbe(inputQuery)
356
412
  ? compileObjectQueryInternal(projectId, inputQuery, ctx)
@@ -389,7 +445,7 @@ function compileLimit(
389
445
  rawLimit: number,
390
446
  ctx: CompileContext
391
447
  ): CompiledPgObjectQuery {
392
- const input = compileObjectQueryInternal(projectId, inputQuery, exactContext)
448
+ const input = compileObjectQueryInternal(projectId, inputQuery, exactContext(ctx))
393
449
  const limit = Math.max(0, rawLimit)
394
450
  const rowLimit = ctx.probeLimit ? limit + 1 : limit
395
451
 
@@ -418,9 +474,10 @@ function compilePage(
418
474
  projectId: string,
419
475
  inputQuery: ObjectQuery,
420
476
  rawPageSize: number,
421
- pageToken: string | undefined
477
+ pageToken: string | undefined,
478
+ ctx: CompileContext
422
479
  ): CompiledPgObjectQuery {
423
- const input = compileObjectQueryInternal(projectId, inputQuery, exactContext)
480
+ const input = compileObjectQueryInternal(projectId, inputQuery, exactContext(ctx))
424
481
  const pageSize = Math.max(0, rawPageSize)
425
482
  const cursor = pageToken ? decodePageToken(pageToken, input.order.fields) : undefined
426
483
  const cursorPredicate = cursor
@@ -457,30 +514,31 @@ function compileTraversal(
457
514
  inputQuery: ObjectQuery,
458
515
  linkId: string,
459
516
  direction: "outgoing" | "incoming",
460
- sourceObjectTypeId?: string
517
+ sourceObjectTypeId: string | undefined,
518
+ ctx: CompileContext
461
519
  ): CompiledPgObjectQuery {
462
- const input = compileObjectQueryInternal(projectId, inputQuery, exactContext)
520
+ const input = compileObjectQueryInternal(projectId, inputQuery, exactContext(ctx))
463
521
  const outputAlias = direction === "outgoing" ? "target_object" : "source_object"
464
522
  const joinSql =
465
523
  direction === "outgoing"
466
524
  ? `
467
- JOIN links AS edge
525
+ JOIN ${ctx.source.linksTable} AS edge
468
526
  ON edge.project_id = input.project_id
469
527
  AND edge.source_type_id = input.object_type_id
470
528
  AND edge.source_id = input.primary_id
471
529
  AND edge.link_id = ?
472
- JOIN objects AS target_object
530
+ JOIN ${ctx.source.objectsTable} AS target_object
473
531
  ON target_object.project_id = edge.project_id
474
532
  AND target_object.object_type_id = edge.target_type_id
475
533
  AND target_object.primary_id = edge.target_id
476
534
  `
477
535
  : `
478
- JOIN links AS edge
536
+ JOIN ${ctx.source.linksTable} AS edge
479
537
  ON edge.project_id = input.project_id
480
538
  AND edge.target_type_id = input.object_type_id
481
539
  AND edge.target_id = input.primary_id
482
540
  AND edge.link_id = ?${sourceObjectTypeId === undefined ? "" : "\n AND edge.source_type_id = ?"}
483
- JOIN objects AS source_object
541
+ JOIN ${ctx.source.objectsTable} AS source_object
484
542
  ON source_object.project_id = edge.project_id
485
543
  AND source_object.object_type_id = edge.source_type_id
486
544
  AND source_object.primary_id = edge.source_id
@@ -527,13 +585,15 @@ interface ExpansionParent {
527
585
  function compileExpand(
528
586
  projectId: string,
529
587
  inputQuery: ObjectQuery,
530
- expansions: readonly ObjectExpansion[]
588
+ expansions: readonly ObjectExpansion[],
589
+ ctx: CompileContext
531
590
  ): CompiledPgObjectQuery {
532
- const input = compileObjectQueryInternal(projectId, inputQuery, exactContext)
591
+ const input = compileObjectQueryInternal(projectId, inputQuery, exactContext(ctx))
533
592
  const expand = compileExpansionsObject(
534
593
  expansions,
535
594
  { project: "input.project_id", type: "input.object_type_id", id: "input.primary_id" },
536
- ""
595
+ "",
596
+ ctx
537
597
  )
538
598
  const inputOrder = compileOrder(input.order.fields, "input", "input._cursor_properties")
539
599
  const sql = `
@@ -561,13 +621,14 @@ function compileExpand(
561
621
  function compileExpansionsObject(
562
622
  expansions: readonly ObjectExpansion[],
563
623
  parent: ExpansionParent,
564
- pathPrefix: string
624
+ pathPrefix: string,
625
+ ctx: CompileContext
565
626
  ): CompiledPredicate {
566
627
  const parts: string[] = []
567
628
  const args: unknown[] = []
568
629
  expansions.forEach((expansion, index) => {
569
630
  const path = pathPrefix === "" ? `${index}` : `${pathPrefix}_${index}`
570
- const value = compileExpansionValue(expansion, parent, path)
631
+ const value = compileExpansionValue(expansion, parent, path, ctx)
571
632
  parts.push("?::text", value.sql)
572
633
  args.push(expansion.linkId, ...value.args)
573
634
  })
@@ -583,7 +644,8 @@ function compileExpansionsObject(
583
644
  function compileExpansionValue(
584
645
  expansion: ObjectExpansion,
585
646
  parent: ExpansionParent,
586
- path: string
647
+ path: string,
648
+ ctx: CompileContext
587
649
  ): CompiledPredicate {
588
650
  const edge = `edge_${path}`
589
651
  const target = `tgt_${path}`
@@ -596,7 +658,7 @@ function compileExpansionValue(
596
658
  const parentType = incoming ? `${edge}.target_type_id` : `${edge}.source_type_id`
597
659
  const parentId = incoming ? `${edge}.target_id` : `${edge}.source_id`
598
660
 
599
- const child = compileExpansionChildJson(expansion, edge, target, path)
661
+ const child = compileExpansionChildJson(expansion, edge, target, path, ctx)
600
662
  const order = compileExpansionOrder(expansion, target, neighborType, neighborId)
601
663
 
602
664
  const whereParts = [
@@ -613,8 +675,8 @@ function compileExpansionValue(
613
675
 
614
676
  const inner = `
615
677
  SELECT ${child.sql} AS elem, row_number() OVER (ORDER BY ${order.sql}) AS _ord
616
- FROM links AS ${edge}
617
- JOIN objects AS ${target}
678
+ FROM ${ctx.source.linksTable} AS ${edge}
679
+ JOIN ${ctx.source.objectsTable} AS ${target}
618
680
  ON ${target}.project_id = ${edge}.project_id
619
681
  AND ${target}.object_type_id = ${neighborType}
620
682
  AND ${target}.primary_id = ${neighborId}
@@ -644,7 +706,8 @@ function compileExpansionChildJson(
644
706
  expansion: ObjectExpansion,
645
707
  edge: string,
646
708
  target: string,
647
- path: string
709
+ path: string,
710
+ ctx: CompileContext
648
711
  ): CompiledPredicate {
649
712
  const fields = [
650
713
  `'projectId', ${target}.project_id`,
@@ -667,7 +730,8 @@ function compileExpansionChildJson(
667
730
  type: `${target}.object_type_id`,
668
731
  id: `${target}.primary_id`,
669
732
  },
670
- path
733
+ path,
734
+ ctx
671
735
  )
672
736
  fields.push(`'links', ${nested.sql}`)
673
737
  args.push(...nested.args)
@@ -711,14 +775,15 @@ function compileExpansionOrder(
711
775
  function compileSet(
712
776
  projectId: string,
713
777
  op: ObjectQuerySetOperation,
714
- inputs: readonly ObjectQuery[]
778
+ inputs: readonly ObjectQuery[],
779
+ ctx: CompileContext
715
780
  ): CompiledPgObjectQuery {
716
781
  if (inputs.length === 0) {
717
782
  const order = compileOrder(identityOrderFields())
718
783
  return {
719
784
  sql: `
720
785
  SELECT *, properties AS _cursor_properties
721
- FROM objects
786
+ FROM ${ctx.source.objectsTable}
722
787
  WHERE 1 = 0
723
788
  ORDER BY ${order.sql}
724
789
  `,
@@ -733,7 +798,7 @@ function compileSet(
733
798
  }
734
799
 
735
800
  const compiledInputs = inputs.map((input) =>
736
- compileObjectQueryInternal(projectId, input, exactContext)
801
+ compileObjectQueryInternal(projectId, input, exactContext(ctx))
737
802
  )
738
803
  const identities = compileSetIdentities(op, compiledInputs)
739
804
  const order = compileOrder(identityOrderFields())
@@ -741,7 +806,7 @@ function compileSet(
741
806
  const sql = `
742
807
  SELECT selected.*, selected.properties AS _cursor_properties
743
808
  FROM (${identities.sql}) AS ids
744
- JOIN objects AS selected
809
+ JOIN ${ctx.source.objectsTable} AS selected
745
810
  ON selected.project_id = ?
746
811
  AND selected.object_type_id = ids.object_type_id
747
812
  AND selected.primary_id = ids.primary_id
@@ -799,19 +864,29 @@ function compileProject(
799
864
  }
800
865
  }
801
866
 
802
- function compileAggregateSource(projectId: string, query: ObjectQuery): CompiledAggregateSource {
867
+ function compileAggregateSource(
868
+ projectId: string,
869
+ query: ObjectQuery,
870
+ source: PgObjectQuerySource
871
+ ): CompiledAggregateSource {
803
872
  switch (query.kind) {
804
873
  case "start":
805
- return compileAggregateStart(projectId, query)
874
+ return compileAggregateStart(projectId, query, source)
806
875
  case "refs":
807
- return compileAggregateRefs(projectId, query)
876
+ return compileAggregateRefs(projectId, query, source)
808
877
  case "filter":
809
- return compileAggregateWhere(projectId, query.input, compilePredicate(query.predicate))
878
+ return compileAggregateWhere(
879
+ projectId,
880
+ query.input,
881
+ compilePredicate(query.predicate),
882
+ source
883
+ )
810
884
  case "text": {
811
885
  return compileAggregateWhere(
812
886
  projectId,
813
887
  query.input,
814
- compileTextSearchPredicate(query.query, query.fields, query.fieldsByObjectType)
888
+ compileTextSearchPredicate(query.query, query.fields, query.fieldsByObjectType),
889
+ source
815
890
  )
816
891
  }
817
892
  case "traverse":
@@ -820,18 +895,19 @@ function compileAggregateSource(projectId: string, query: ObjectQuery): Compiled
820
895
  query.input,
821
896
  query.linkId,
822
897
  query.direction,
823
- query.sourceObjectTypeId
898
+ query.sourceObjectTypeId,
899
+ source
824
900
  )
825
901
  case "set":
826
- return compileAggregateSet(projectId, query.op, query.inputs)
902
+ return compileAggregateSet(projectId, query.op, query.inputs, source)
827
903
  case "sort":
828
904
  case "project":
829
905
  // `expand` is output-shaping, like sort/project: aggregates ignore it.
830
906
  case "expand":
831
- return compileAggregateSource(projectId, query.input)
907
+ return compileAggregateSource(projectId, query.input, source)
832
908
  case "limit":
833
909
  case "page":
834
- return compileRowQueryAggregateSource(projectId, query)
910
+ return compileRowQueryAggregateSource(projectId, query, source)
835
911
  case "vector":
836
912
  throw new Error(
837
913
  `[SixbPg] PostgreSQL object storage does not support query node '${query.kind}'`
@@ -841,7 +917,8 @@ function compileAggregateSource(projectId: string, query: ObjectQuery): Compiled
841
917
 
842
918
  function compileAggregateStart(
843
919
  projectId: string,
844
- query: Extract<ObjectQuery, { kind: "start" }>
920
+ query: Extract<ObjectQuery, { kind: "start" }>,
921
+ source: PgObjectQuerySource
845
922
  ): CompiledAggregateSource {
846
923
  if (query.includeSubtypes === true) {
847
924
  throw new Error("[SixbPg] PostgreSQL object storage does not support start.includeSubtypes")
@@ -850,7 +927,7 @@ function compileAggregateStart(
850
927
  return {
851
928
  sql: `
852
929
  SELECT project_id, object_type_id, primary_id, properties
853
- FROM objects
930
+ FROM ${source.objectsTable}
854
931
  WHERE project_id = ? AND object_type_id = ?
855
932
  `,
856
933
  args: [projectId, query.objectTypeId],
@@ -859,7 +936,8 @@ function compileAggregateStart(
859
936
 
860
937
  function compileAggregateRefs(
861
938
  projectId: string,
862
- query: Extract<ObjectQuery, { kind: "refs" }>
939
+ query: Extract<ObjectQuery, { kind: "refs" }>,
940
+ source: PgObjectQuerySource
863
941
  ): CompiledAggregateSource {
864
942
  if (query.refs.length === 0) {
865
943
  throw new Error("[SixbPg] PostgreSQL object storage requires at least one ref")
@@ -874,7 +952,7 @@ function compileAggregateRefs(
874
952
  ref.value ->> 'primaryId' AS primary_id
875
953
  FROM jsonb_array_elements(?::text::jsonb) AS ref(value)
876
954
  ) AS requested
877
- JOIN objects AS selected
955
+ JOIN ${source.objectsTable} AS selected
878
956
  ON selected.project_id = ?
879
957
  AND selected.object_type_id = requested.object_type_id
880
958
  AND selected.primary_id = requested.primary_id
@@ -886,9 +964,10 @@ function compileAggregateRefs(
886
964
  function compileAggregateWhere(
887
965
  projectId: string,
888
966
  inputQuery: ObjectQuery,
889
- predicate: CompiledPredicate
967
+ predicate: CompiledPredicate,
968
+ source: PgObjectQuerySource
890
969
  ): CompiledAggregateSource {
891
- const input = compileAggregateSource(projectId, inputQuery)
970
+ const input = compileAggregateSource(projectId, inputQuery, source)
892
971
  return {
893
972
  sql: `
894
973
  SELECT input.project_id, input.object_type_id, input.primary_id, input.properties
@@ -904,30 +983,31 @@ function compileAggregateTraversal(
904
983
  inputQuery: ObjectQuery,
905
984
  linkId: string,
906
985
  direction: "outgoing" | "incoming",
907
- sourceObjectTypeId?: string
986
+ sourceObjectTypeId: string | undefined,
987
+ source: PgObjectQuerySource
908
988
  ): CompiledAggregateSource {
909
- const input = compileAggregateSource(projectId, inputQuery)
989
+ const input = compileAggregateSource(projectId, inputQuery, source)
910
990
  const outputAlias = direction === "outgoing" ? "target_object" : "source_object"
911
991
  const joinSql =
912
992
  direction === "outgoing"
913
993
  ? `
914
- JOIN links AS edge
994
+ JOIN ${source.linksTable} AS edge
915
995
  ON edge.project_id = input.project_id
916
996
  AND edge.source_type_id = input.object_type_id
917
997
  AND edge.source_id = input.primary_id
918
998
  AND edge.link_id = ?
919
- JOIN objects AS target_object
999
+ JOIN ${source.objectsTable} AS target_object
920
1000
  ON target_object.project_id = edge.project_id
921
1001
  AND target_object.object_type_id = edge.target_type_id
922
1002
  AND target_object.primary_id = edge.target_id
923
1003
  `
924
1004
  : `
925
- JOIN links AS edge
1005
+ JOIN ${source.linksTable} AS edge
926
1006
  ON edge.project_id = input.project_id
927
1007
  AND edge.target_type_id = input.object_type_id
928
1008
  AND edge.target_id = input.primary_id
929
1009
  AND edge.link_id = ?${sourceObjectTypeId === undefined ? "" : "\n AND edge.source_type_id = ?"}
930
- JOIN objects AS source_object
1010
+ JOIN ${source.objectsTable} AS source_object
931
1011
  ON source_object.project_id = edge.project_id
932
1012
  AND source_object.object_type_id = edge.source_type_id
933
1013
  AND source_object.primary_id = edge.source_id
@@ -954,26 +1034,27 @@ function compileAggregateTraversal(
954
1034
  function compileAggregateSet(
955
1035
  projectId: string,
956
1036
  op: ObjectQuerySetOperation,
957
- inputs: readonly ObjectQuery[]
1037
+ inputs: readonly ObjectQuery[],
1038
+ source: PgObjectQuerySource
958
1039
  ): CompiledAggregateSource {
959
1040
  if (inputs.length === 0) {
960
1041
  return {
961
1042
  sql: `
962
1043
  SELECT project_id, object_type_id, primary_id, properties
963
- FROM objects
1044
+ FROM ${source.objectsTable}
964
1045
  WHERE 1 = 0
965
1046
  `,
966
1047
  args: [],
967
1048
  }
968
1049
  }
969
1050
 
970
- const compiledInputs = inputs.map((input) => compileAggregateSource(projectId, input))
1051
+ const compiledInputs = inputs.map((input) => compileAggregateSource(projectId, input, source))
971
1052
  const identities = compileSetIdentities(op, compiledInputs)
972
1053
  return {
973
1054
  sql: `
974
1055
  SELECT selected.project_id, selected.object_type_id, selected.primary_id, selected.properties
975
1056
  FROM (${identities.sql}) AS ids
976
- JOIN objects AS selected
1057
+ JOIN ${source.objectsTable} AS selected
977
1058
  ON selected.project_id = ?
978
1059
  AND selected.object_type_id = ids.object_type_id
979
1060
  AND selected.primary_id = ids.primary_id
@@ -984,9 +1065,13 @@ function compileAggregateSet(
984
1065
 
985
1066
  function compileRowQueryAggregateSource(
986
1067
  projectId: string,
987
- query: ObjectQuery
1068
+ query: ObjectQuery,
1069
+ source: PgObjectQuerySource
988
1070
  ): CompiledAggregateSource {
989
- const rowQuery = compileObjectQueryInternal(projectId, query, exactContext)
1071
+ const rowQuery = compileObjectQueryInternal(projectId, query, {
1072
+ probeLimit: false,
1073
+ source,
1074
+ })
990
1075
  return {
991
1076
  sql: `
992
1077
  SELECT input.project_id, input.object_type_id, input.primary_id, input.properties