@mastra/pg 1.9.1-alpha.0 → 1.9.1

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/CHANGELOG.md CHANGED
@@ -1,5 +1,37 @@
1
1
  # @mastra/pg
2
2
 
3
+ ## 1.9.1
4
+
5
+ ### Patch Changes
6
+
7
+ - Fixed vector similarity queries to leverage HNSW and IVFFlat indexes. When querying without filters on an HNSW or IVFFlat-indexed table, ORDER BY and LIMIT are now placed inside the CTE so PostgreSQL can use the index for faster approximate nearest neighbor searches instead of scanning all rows. ([#14574](https://github.com/mastra-ai/mastra/pull/14574))
8
+
9
+ - Fixed `batchInsert` and `batchUpdate` in `@mastra/pg` to run on a single Postgres transaction connection. ([#15312](https://github.com/mastra-ai/mastra/pull/15312))
10
+
11
+ This prevents pooled `BEGIN`/`COMMIT`/`ROLLBACK` calls from landing on different connections and leaving idle transactions open during batch writes.
12
+
13
+ - Fixed "column does not exist" errors when using experiment review features on databases created before the review pipeline was introduced. Startup now automatically migrates older experiment tables to the latest schema. ([#15304](https://github.com/mastra-ai/mastra/pull/15304))
14
+
15
+ - Fixed vector operations failing when pgvector extension is installed in a custom schema. The search_path is now set before index creation and vector similarity queries, ensuring operator classes (e.g. vector_cosine_ops) and distance operators (e.g. <=>) resolve correctly regardless of where the extension is installed. Previously, only table creation set the search_path, causing CREATE INDEX and query operations to fail with unresolvable operator errors. ([#14526](https://github.com/mastra-ai/mastra/pull/14526))
16
+
17
+ - Added `entityVersionId`, `parentEntityVersionId`, and `rootEntityVersionId` columns to observability storage tables (spans, metrics, scores, feedback, logs) for filtering and grouping traces by entity version. Added ALTER TABLE migrations for existing databases. Added `targetType`, `targetId`, `agentVersion`, and `status` filters to `listExperiments`, and `traceId` and `status` filters to `listExperimentResults`. ([#15317](https://github.com/mastra-ai/mastra/pull/15317))
18
+
19
+ - Updated dependencies [[`87df955`](https://github.com/mastra-ai/mastra/commit/87df955c028660c075873fd5d74af28233ce32eb), [`8fad147`](https://github.com/mastra-ai/mastra/commit/8fad14759804179c8e080ce4d9dec6ef1a808b31), [`582644c`](https://github.com/mastra-ai/mastra/commit/582644c4a87f83b4f245a84d72b9e8590585012e), [`cbdf3e1`](https://github.com/mastra-ai/mastra/commit/cbdf3e12b3d0c30a6e5347be658e2009648c130a), [`8fe46d3`](https://github.com/mastra-ai/mastra/commit/8fe46d354027f3f0f0846e64219772348de106dd), [`18c67db`](https://github.com/mastra-ai/mastra/commit/18c67dbb9c9ebc26f26f65f7d3ff836e5691ef46), [`4ba3bb1`](https://github.com/mastra-ai/mastra/commit/4ba3bb1e465ad2ddaba3bbf2bc47e0faec32985e), [`5d84914`](https://github.com/mastra-ai/mastra/commit/5d84914e0e520c642a40329b210b413fcd139898), [`8dcc77e`](https://github.com/mastra-ai/mastra/commit/8dcc77e78a5340f5848f74b9e9f1b3da3513c1f5), [`aa67fc5`](https://github.com/mastra-ai/mastra/commit/aa67fc59ee8a5eeff1f23eb05970b8d7a536c8ff), [`fd2f314`](https://github.com/mastra-ai/mastra/commit/fd2f31473d3449b6b97e837ef8641264377f41a7), [`fa8140b`](https://github.com/mastra-ai/mastra/commit/fa8140bcd4251d2e3ac85fdc5547dfc4f372b5be), [`190f452`](https://github.com/mastra-ai/mastra/commit/190f45258b0640e2adfc8219fa3258cdc5b8f071), [`e80fead`](https://github.com/mastra-ai/mastra/commit/e80fead1412cc0d1b2f7d6a1ce5017d9e0098ff7), [`0287b64`](https://github.com/mastra-ai/mastra/commit/0287b644a5c3272755cf3112e71338106664103b), [`7e7bf60`](https://github.com/mastra-ai/mastra/commit/7e7bf606886bf374a6f9d4ca9b09dd83d0533372), [`184907d`](https://github.com/mastra-ai/mastra/commit/184907d775d8609c03c26e78ccaf37315f3aa287), [`075e91a`](https://github.com/mastra-ai/mastra/commit/075e91a4549baf46ad7a42a6a8ac8dfa78cc09e6), [`0c4cd13`](https://github.com/mastra-ai/mastra/commit/0c4cd131931c04ac5405373c932a242dbe88edd6), [`b16a753`](https://github.com/mastra-ai/mastra/commit/b16a753d5748440248d7df82e29bb987a9c8386c)]:
20
+ - @mastra/core@1.25.0
21
+
22
+ ## 1.9.1-alpha.1
23
+
24
+ ### Patch Changes
25
+
26
+ - Fixed vector similarity queries to leverage HNSW and IVFFlat indexes. When querying without filters on an HNSW or IVFFlat-indexed table, ORDER BY and LIMIT are now placed inside the CTE so PostgreSQL can use the index for faster approximate nearest neighbor searches instead of scanning all rows. ([#14574](https://github.com/mastra-ai/mastra/pull/14574))
27
+
28
+ - Fixed vector operations failing when pgvector extension is installed in a custom schema. The search_path is now set before index creation and vector similarity queries, ensuring operator classes (e.g. vector_cosine_ops) and distance operators (e.g. <=>) resolve correctly regardless of where the extension is installed. Previously, only table creation set the search_path, causing CREATE INDEX and query operations to fail with unresolvable operator errors. ([#14526](https://github.com/mastra-ai/mastra/pull/14526))
29
+
30
+ - Added `entityVersionId`, `parentEntityVersionId`, and `rootEntityVersionId` columns to observability storage tables (spans, metrics, scores, feedback, logs) for filtering and grouping traces by entity version. Added ALTER TABLE migrations for existing databases. Added `targetType`, `targetId`, `agentVersion`, and `status` filters to `listExperiments`, and `traceId` and `status` filters to `listExperimentResults`. ([#15317](https://github.com/mastra-ai/mastra/pull/15317))
31
+
32
+ - Updated dependencies [[`cbdf3e1`](https://github.com/mastra-ai/mastra/commit/cbdf3e12b3d0c30a6e5347be658e2009648c130a), [`8fe46d3`](https://github.com/mastra-ai/mastra/commit/8fe46d354027f3f0f0846e64219772348de106dd), [`18c67db`](https://github.com/mastra-ai/mastra/commit/18c67dbb9c9ebc26f26f65f7d3ff836e5691ef46), [`8dcc77e`](https://github.com/mastra-ai/mastra/commit/8dcc77e78a5340f5848f74b9e9f1b3da3513c1f5), [`aa67fc5`](https://github.com/mastra-ai/mastra/commit/aa67fc59ee8a5eeff1f23eb05970b8d7a536c8ff), [`fa8140b`](https://github.com/mastra-ai/mastra/commit/fa8140bcd4251d2e3ac85fdc5547dfc4f372b5be), [`190f452`](https://github.com/mastra-ai/mastra/commit/190f45258b0640e2adfc8219fa3258cdc5b8f071), [`7e7bf60`](https://github.com/mastra-ai/mastra/commit/7e7bf606886bf374a6f9d4ca9b09dd83d0533372), [`184907d`](https://github.com/mastra-ai/mastra/commit/184907d775d8609c03c26e78ccaf37315f3aa287), [`0c4cd13`](https://github.com/mastra-ai/mastra/commit/0c4cd131931c04ac5405373c932a242dbe88edd6), [`b16a753`](https://github.com/mastra-ai/mastra/commit/b16a753d5748440248d7df82e29bb987a9c8386c)]:
33
+ - @mastra/core@1.25.0-alpha.3
34
+
3
35
  ## 1.9.1-alpha.0
4
36
 
5
37
  ### Patch Changes
@@ -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.9.1-alpha.0"
6
+ version: "1.9.1"
7
7
  ---
8
8
 
9
9
  ## When to use
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.9.1-alpha.0",
2
+ "version": "1.9.1",
3
3
  "package": "@mastra/pg",
4
4
  "exports": {},
5
5
  "modules": {}
package/dist/index.cjs CHANGED
@@ -734,6 +734,25 @@ var PgVector = class extends vector.MastraVector {
734
734
  return null;
735
735
  }
736
736
  }
737
+ /**
738
+ * Sets search_path on the client connection so that vector operators (e.g. <=>, vector_cosine_ops)
739
+ * are resolvable when the pgvector extension is installed in a non-default schema.
740
+ *
741
+ * PostgreSQL's default search_path is ("$user", public). If the extension lives in a custom schema
742
+ * (e.g. "myapp"), operator classes and distance operators won't resolve without this.
743
+ */
744
+ async ensureSearchPath(client) {
745
+ if (!this.vectorExtensionSchema) {
746
+ await this.detectVectorExtensionSchema(client);
747
+ }
748
+ if (this.vectorExtensionSchema && this.vectorExtensionSchema !== "public" && this.vectorExtensionSchema !== "pg_catalog") {
749
+ const schemas = /* @__PURE__ */ new Set();
750
+ schemas.add(this.vectorExtensionSchema);
751
+ if (this.schema) schemas.add(this.schema);
752
+ schemas.add("public");
753
+ await client.query(`SET search_path TO ${[...schemas].map((s) => `"${s}"`).join(", ")}`);
754
+ }
755
+ }
737
756
  /**
738
757
  * Checks if the installed pgvector version supports halfvec type.
739
758
  * halfvec was introduced in pgvector 0.7.0.
@@ -947,6 +966,7 @@ var PgVector = class extends vector.MastraVector {
947
966
  }
948
967
  const client = await this.pool.connect();
949
968
  try {
969
+ await this.ensureSearchPath(client);
950
970
  await client.query("BEGIN");
951
971
  const translatedFilter = this.transformFilter(filter);
952
972
  const { sql: filterQuery, values: filterValues } = buildFilterQuery(translatedFilter, minScore, topK);
@@ -966,7 +986,23 @@ var PgVector = class extends vector.MastraVector {
966
986
  const qualifiedVectorType = this.getVectorTypeName(indexInfo.vectorType, indexInfo.dimension);
967
987
  const distanceExpr = `embedding ${ops.distanceOperator} '${vectorStr}'::${qualifiedVectorType}`;
968
988
  const scoreExpr = ops.scoreExpr(distanceExpr);
969
- const query = `
989
+ const hasFilter = filterQuery.trim().length > 0;
990
+ const useIndexedOrder = indexInfo.type === "hnsw" && !hasFilter && minScore <= 0;
991
+ const query = useIndexedOrder ? `
992
+ WITH vector_scores AS (
993
+ SELECT
994
+ vector_id as id,
995
+ ${scoreExpr} as score,
996
+ metadata
997
+ ${includeVector ? ", embedding" : ""}
998
+ FROM ${tableName}
999
+ ORDER BY ${distanceExpr}
1000
+ LIMIT $2
1001
+ )
1002
+ SELECT *
1003
+ FROM vector_scores
1004
+ WHERE score > $1
1005
+ ORDER BY score DESC` : `
970
1006
  WITH vector_scores AS (
971
1007
  SELECT
972
1008
  vector_id as id,
@@ -1019,6 +1055,7 @@ var PgVector = class extends vector.MastraVector {
1019
1055
  const { tableName } = this.getTableName(indexName);
1020
1056
  const client = await this.pool.connect();
1021
1057
  try {
1058
+ await this.ensureSearchPath(client);
1022
1059
  await client.query("BEGIN");
1023
1060
  if (deleteFilter) {
1024
1061
  this.logger?.debug(`Deleting vectors matching filter before upsert`, { indexName, deleteFilter });
@@ -1269,9 +1306,6 @@ var PgVector = class extends vector.MastraVector {
1269
1306
  }
1270
1307
  });
1271
1308
  }
1272
- if (this.schema && this.vectorExtensionSchema && this.schema !== this.vectorExtensionSchema && this.vectorExtensionSchema !== "pg_catalog") {
1273
- await client.query(`SET search_path TO ${this.getSchemaName()}, "${this.vectorExtensionSchema}"`);
1274
- }
1275
1309
  const qualifiedVectorType = this.getVectorTypeName(vectorType);
1276
1310
  await client.query(`
1277
1311
  CREATE TABLE IF NOT EXISTS ${tableName} (
@@ -1414,6 +1448,7 @@ var PgVector = class extends vector.MastraVector {
1414
1448
  this.describeIndexCache.delete(indexName);
1415
1449
  return;
1416
1450
  }
1451
+ await this.ensureSearchPath(client);
1417
1452
  const effectiveVectorType = existingIndexInfo?.vectorType ?? vectorType;
1418
1453
  const metricOp = this.getVectorOps(effectiveVectorType, metric).operatorClass;
1419
1454
  let indexSQL;
@@ -1764,6 +1799,7 @@ var PgVector = class extends vector.MastraVector {
1764
1799
  });
1765
1800
  }
1766
1801
  client = await this.pool.connect();
1802
+ await this.ensureSearchPath(client);
1767
1803
  const { tableName } = this.getTableName(indexName);
1768
1804
  const indexInfo = await this.getIndexInfo({ indexName });
1769
1805
  const qualifiedVectorType = this.getVectorTypeName(indexInfo.vectorType, indexInfo.dimension);
@@ -2002,6 +2038,7 @@ var PoolAdapter = class {
2002
2038
  constructor($pool) {
2003
2039
  this.$pool = $pool;
2004
2040
  }
2041
+ $pool;
2005
2042
  connect() {
2006
2043
  return this.$pool.connect();
2007
2044
  }
@@ -2070,6 +2107,7 @@ var TransactionClient = class {
2070
2107
  constructor(client) {
2071
2108
  this.client = client;
2072
2109
  }
2110
+ client;
2073
2111
  async none(query, values) {
2074
2112
  await this.client.query(query, values);
2075
2113
  return null;
@@ -5565,6 +5603,22 @@ var ExperimentsPG = class _ExperimentsPG extends storage.ExperimentsStorage {
5565
5603
  conditions.push(`"datasetId" = $${paramIndex++}`);
5566
5604
  queryParams.push(args.datasetId);
5567
5605
  }
5606
+ if (args.targetType) {
5607
+ conditions.push(`"targetType" = $${paramIndex++}`);
5608
+ queryParams.push(args.targetType);
5609
+ }
5610
+ if (args.targetId) {
5611
+ conditions.push(`"targetId" = $${paramIndex++}`);
5612
+ queryParams.push(args.targetId);
5613
+ }
5614
+ if (args.agentVersion) {
5615
+ conditions.push(`"agentVersion" = $${paramIndex++}`);
5616
+ queryParams.push(args.agentVersion);
5617
+ }
5618
+ if (args.status) {
5619
+ conditions.push(`"status" = $${paramIndex++}`);
5620
+ queryParams.push(args.status);
5621
+ }
5568
5622
  const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
5569
5623
  const countResult = await this.#db.client.one(
5570
5624
  `SELECT COUNT(*) as count FROM ${tableName} ${whereClause}`,
@@ -5753,9 +5807,21 @@ var ExperimentsPG = class _ExperimentsPG extends storage.ExperimentsStorage {
5753
5807
  try {
5754
5808
  const { page, perPage: perPageInput } = args.pagination;
5755
5809
  const tableName = getTableName2({ indexName: storage.TABLE_EXPERIMENT_RESULTS, schemaName: getSchemaName2(this.#schema) });
5810
+ const conditions = ['"experimentId" = $1'];
5811
+ const queryParams = [args.experimentId];
5812
+ let paramIndex = 2;
5813
+ if (args.traceId) {
5814
+ conditions.push(`"traceId" = $${paramIndex++}`);
5815
+ queryParams.push(args.traceId);
5816
+ }
5817
+ if (args.status) {
5818
+ conditions.push(`"status" = $${paramIndex++}`);
5819
+ queryParams.push(args.status);
5820
+ }
5821
+ const whereClause = `WHERE ${conditions.join(" AND ")}`;
5756
5822
  const countResult = await this.#db.client.one(
5757
- `SELECT COUNT(*) as count FROM ${tableName} WHERE "experimentId" = $1`,
5758
- [args.experimentId]
5823
+ `SELECT COUNT(*) as count FROM ${tableName} ${whereClause}`,
5824
+ queryParams
5759
5825
  );
5760
5826
  const total = parseInt(countResult.count, 10);
5761
5827
  if (total === 0) {
@@ -5765,8 +5831,8 @@ var ExperimentsPG = class _ExperimentsPG extends storage.ExperimentsStorage {
5765
5831
  const { offset, perPage: perPageForResponse } = storage.calculatePagination(page, perPageInput, perPage);
5766
5832
  const limitValue = perPageInput === false ? total : perPage;
5767
5833
  const rows = await this.#db.client.manyOrNone(
5768
- `SELECT * FROM ${tableName} WHERE "experimentId" = $1 ORDER BY "startedAt" ASC LIMIT $2 OFFSET $3`,
5769
- [args.experimentId, limitValue, offset]
5834
+ `SELECT * FROM ${tableName} ${whereClause} ORDER BY "startedAt" ASC LIMIT $${paramIndex} OFFSET $${paramIndex + 1}`,
5835
+ [...queryParams, limitValue, offset]
5770
5836
  );
5771
5837
  return {
5772
5838
  results: (rows || []).map((row) => this.transformExperimentResultRow(row)),