@mastra/pg 1.32.0-alpha.3 → 1.32.0-alpha.4

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.
@@ -3,7 +3,7 @@ name: mastra-pg
3
3
  description: Documentation for @mastra/pg. Use when working with @mastra/pg APIs, configuration, or implementation.
4
4
  metadata:
5
5
  package: "@mastra/pg"
6
- version: "1.32.0-alpha.3"
6
+ version: "1.32.0-alpha.4"
7
7
  ---
8
8
 
9
9
  ## When to use
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.32.0-alpha.3",
2
+ "version": "1.32.0-alpha.4",
3
3
  "package": "@mastra/pg",
4
4
  "exports": {},
5
5
  "modules": {}
package/dist/index.cjs CHANGED
@@ -19211,7 +19211,26 @@ async function getScorePercentiles(client, schema, args) {
19211
19211
  const TRACE_STATUS_SQL = `CASE WHEN r."error" IS NOT NULL THEN 'error' ELSE 'success' END`;
19212
19212
  /** Core versions without the field reject it in strict query results, so it is only returned when core knows it. */
19213
19213
  const timeToFirstChunkSupported = "timeToFirstChunkMs" in _mastra_core_storage.TRACE_QUERY_FIELD_REGISTRY.trace;
19214
- const timeToFirstChunkFeatures = timeToFirstChunkSupported ? ["trace-query-time-to-first-chunk"] : [];
19214
+ /** Core before the sort rejects `orderBy` on the field, so the sort is only declared when core plans it. */
19215
+ const timeToFirstChunkSortSupported = _mastra_core_storage.TRACE_QUERY_ORDER_FIELDS?.includes("timeToFirstChunkMs") === true;
19216
+ const timeToFirstChunkFeatures = [...timeToFirstChunkSupported ? ["trace-query-time-to-first-chunk"] : [], ...timeToFirstChunkSortSupported ? ["trace-query-time-to-first-chunk-sort"] : []];
19217
+ /**
19218
+ * Keyset bounds for a cursor's sort value: terms for rows strictly past it in `direction`, and the
19219
+ * condition for rows level with it. Empty values sort last in both directions, so they are past
19220
+ * every value and level only with each other.
19221
+ */
19222
+ function keysetSortBounds(field, direction, sortValue, values) {
19223
+ if (sortValue === null) return {
19224
+ past: [],
19225
+ level: `${field} IS NULL`
19226
+ };
19227
+ values.push(sortValue);
19228
+ const parameter = `$${values.length}::${typeof sortValue === "number" ? "float8" : "timestamptz"}`;
19229
+ return {
19230
+ past: [`${field} ${direction === "asc" ? ">" : "<"} ${parameter}`, `${field} IS NULL`],
19231
+ level: `${field} = ${parameter}`
19232
+ };
19233
+ }
19215
19234
  function durationMsSql(startedAt, endedAt) {
19216
19235
  return `EXTRACT(EPOCH FROM (${endedAt} - ${startedAt}))::numeric * 1000`;
19217
19236
  }
@@ -19803,8 +19822,8 @@ LIMIT $${values.length}`,
19803
19822
  values
19804
19823
  };
19805
19824
  }
19806
- const orderField = plan.orderBy.field === "startedAt" ? "\"startedAt\"" : "\"endedAt\"";
19807
- const direction = plan.orderBy.direction === "asc" ? "ASC" : "DESC";
19825
+ const orderField = `"${plan.orderBy.field}"`;
19826
+ const direction = `${plan.orderBy.direction === "asc" ? "ASC" : "DESC"} NULLS LAST`;
19808
19827
  if (plan.paginationMode === "page") {
19809
19828
  values.push(plan.perPage, plan.page * plan.perPage);
19810
19829
  return {
@@ -19818,10 +19837,9 @@ LIMIT $${values.length - 1} OFFSET $${values.length}`,
19818
19837
  }
19819
19838
  let pageCondition = "";
19820
19839
  if (plan.cursor) {
19821
- const comparison = plan.orderBy.direction === "asc" ? ">" : "<";
19822
- const sortParameter = `$${values.length + 1}`;
19823
- pageCondition = `WHERE (${orderField} ${comparison} ${sortParameter} OR (${orderField} = ${sortParameter} AND "traceId" > ${`$${values.length + 2}`}))`;
19824
- values.push(plan.cursor.sortValue, plan.cursor.traceId);
19840
+ const { past, level } = keysetSortBounds(orderField, plan.orderBy.direction, plan.cursor.sortValue, values);
19841
+ values.push(plan.cursor.traceId);
19842
+ pageCondition = `WHERE (${[...past, `(${level} AND "traceId" > $${values.length})`].join(" OR ")})`;
19825
19843
  }
19826
19844
  values.push(plan.limit + 1);
19827
19845
  return {
@@ -20154,7 +20172,7 @@ async function queryTraces(client, schema, plan, timeoutMs) {
20154
20172
  traces,
20155
20173
  page: { next: rows.length > plan.limit && last ? _mastra_core_storage.encodeTraceQueryCursor(plan, {
20156
20174
  result: "traces",
20157
- sortValue: last[plan.orderBy.field],
20175
+ sortValue: last[plan.orderBy.field] ?? null,
20158
20176
  traceId: last.traceId
20159
20177
  }) : null }
20160
20178
  });
@@ -20226,11 +20244,8 @@ function selectedKeys(rows, values) {
20226
20244
  function afterCursor(plan, values) {
20227
20245
  if (!plan.cursor) return "TRUE";
20228
20246
  const cursor = plan.cursor;
20229
- values.push(cursor.sortValue);
20230
- const timestamp = `$${values.length}::timestamptz`;
20231
- const field = `s."${plan.orderBy.field}"`;
20232
- const terms = [`${field} ${plan.orderBy.direction === "asc" ? ">" : "<"} ${timestamp}`];
20233
- const equal = [`${field} = ${timestamp}`];
20247
+ const { past: terms, level } = keysetSortBounds(`s."${plan.orderBy.field}"`, plan.orderBy.direction, cursor.sortValue, values);
20248
+ const equal = [level];
20234
20249
  for (const key of identityFields) {
20235
20250
  const ref = `s."${key}" COLLATE "C"`;
20236
20251
  const value = cursor[key];
@@ -20296,7 +20311,7 @@ function compilePostgresSpanQuery(schema, plan) {
20296
20311
  "version"
20297
20312
  ].map((field) => `s."${field}"`).join(", ")}
20298
20313
  FROM candidates s WHERE s."startedAt" >= $1 AND s."startedAt" < $2 AND (${predicate.sql}) AND ${after}
20299
- ORDER BY s."${plan.orderBy.field}" ${plan.orderBy.direction === "asc" ? "ASC" : "DESC"}, ${identityOrder}
20314
+ ORDER BY s."${plan.orderBy.field}" ${plan.orderBy.direction === "asc" ? "ASC" : "DESC"} NULLS LAST, ${identityOrder}
20300
20315
  LIMIT $${values.length}`,
20301
20316
  values
20302
20317
  };