@mastra/pg 1.18.1 → 1.19.0-alpha.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/dist/index.cjs CHANGED
@@ -1971,9 +1971,25 @@ var PinnedClientAdapter = class {
1971
1971
  var RoutingDbClient = class {
1972
1972
  #base;
1973
1973
  #pinned = null;
1974
+ #schemaSnapshot = null;
1974
1975
  constructor(base) {
1975
1976
  this.#base = base;
1976
1977
  }
1978
+ /**
1979
+ * Catalog snapshot for the current init window, or `null` outside it.
1980
+ *
1981
+ * It lives here rather than on `PgDB` because every storage domain builds its
1982
+ * own `PgDB` over this one shared client — hanging the snapshot off the
1983
+ * client means one load serves all of them, and its lifetime lines up exactly
1984
+ * with the pinned-init window that `pin()`/`unpin()` already delimit.
1985
+ */
1986
+ get schemaSnapshot() {
1987
+ return this.#schemaSnapshot;
1988
+ }
1989
+ /** Install (or clear, with `null`) the init-window catalog snapshot. */
1990
+ setSchemaSnapshot(snapshot) {
1991
+ this.#schemaSnapshot = snapshot;
1992
+ }
1977
1993
  /** Returns the currently active client (pinned if set, otherwise base). */
1978
1994
  get active() {
1979
1995
  return this.#pinned ?? this.#base;
@@ -2074,6 +2090,67 @@ function isDuplicateSchemaError(error) {
2074
2090
  return /schema .* already exists/i.test(message);
2075
2091
  }
2076
2092
  //#endregion
2093
+ //#region src/storage/db/schema-snapshot.ts
2094
+ /**
2095
+ * Returns the snapshot currently installed on `client`, but only when it was
2096
+ * taken from the schema the caller operates on. A store configured for another
2097
+ * schema (or a client with no snapshot at all) gets `null` and falls back to
2098
+ * probing the live catalog.
2099
+ */
2100
+ function getSchemaSnapshot(client, schemaName) {
2101
+ const snapshot = client?.schemaSnapshot;
2102
+ if (!snapshot) return null;
2103
+ return snapshot.schemaName === (schemaName || "public") ? snapshot : null;
2104
+ }
2105
+ /**
2106
+ * Reads the catalog for `schemaName` in three queries. Must be called on the
2107
+ * pinned init client so the snapshot reflects what that connection will see.
2108
+ */
2109
+ async function loadSchemaSnapshot(client, schemaName) {
2110
+ const schema = schemaName || "public";
2111
+ const [tableRows, columnRows, indexRows] = await Promise.all([
2112
+ client.manyOrNone(`SELECT tablename FROM pg_catalog.pg_tables WHERE schemaname = $1`, [schema]),
2113
+ client.manyOrNone(`SELECT c.relname AS table_name, a.attname AS column_name
2114
+ FROM pg_catalog.pg_class c
2115
+ JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
2116
+ JOIN pg_catalog.pg_attribute a ON a.attrelid = c.oid
2117
+ WHERE n.nspname = $1
2118
+ AND c.relkind IN ('r', 'p')
2119
+ AND a.attnum > 0
2120
+ AND NOT a.attisdropped`, [schema]),
2121
+ client.manyOrNone(`SELECT c.relname AS indexname, i.indisreplident AS is_replica_identity, i.indisprimary AS is_primary
2122
+ FROM pg_catalog.pg_index i
2123
+ JOIN pg_catalog.pg_class c ON c.oid = i.indexrelid
2124
+ JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
2125
+ WHERE n.nspname = $1`, [schema])
2126
+ ]);
2127
+ const columns = /* @__PURE__ */ new Map();
2128
+ for (const row of columnRows) {
2129
+ let set = columns.get(row.table_name);
2130
+ if (!set) {
2131
+ set = /* @__PURE__ */ new Set();
2132
+ columns.set(row.table_name, set);
2133
+ }
2134
+ set.add(row.column_name);
2135
+ }
2136
+ const indexes = /* @__PURE__ */ new Set();
2137
+ const replicaIdentityIndexes = /* @__PURE__ */ new Set();
2138
+ const primaryKeyIndexes = /* @__PURE__ */ new Set();
2139
+ for (const row of indexRows) {
2140
+ indexes.add(row.indexname);
2141
+ if (row.is_replica_identity) replicaIdentityIndexes.add(row.indexname);
2142
+ if (row.is_primary) primaryKeyIndexes.add(row.indexname.toLowerCase());
2143
+ }
2144
+ return {
2145
+ schemaName: schema,
2146
+ tables: new Set(tableRows.map((r) => r.tablename)),
2147
+ columns,
2148
+ indexes,
2149
+ replicaIdentityIndexes,
2150
+ primaryKeyIndexes
2151
+ };
2152
+ }
2153
+ //#endregion
2077
2154
  //#region src/storage/db/index.ts
2078
2155
  /**
2079
2156
  * Resolves PgDomainConfig to a database client and schema.
@@ -2253,7 +2330,8 @@ function generateTimestampTriggerSQL(tableName, schemaName) {
2253
2330
  schemaName: quotedSchemaName
2254
2331
  });
2255
2332
  const functionName = `${quotedSchemaName}.trigger_set_timestamps`;
2256
- const triggerName = `"${(0, _mastra_core_utils.parseSqlIdentifier)(`${tableName}_timestamps`, "trigger name")}"`;
2333
+ const parsedTriggerName = (0, _mastra_core_utils.parseSqlIdentifier)(`${tableName}_timestamps`, "trigger name");
2334
+ const triggerName = `"${parsedTriggerName}"`;
2257
2335
  return `CREATE OR REPLACE FUNCTION ${functionName}()
2258
2336
  RETURNS TRIGGER AS $$
2259
2337
  BEGIN
@@ -2272,12 +2350,38 @@ BEGIN
2272
2350
  END;
2273
2351
  $$ LANGUAGE plpgsql;
2274
2352
 
2275
- DROP TRIGGER IF EXISTS ${triggerName} ON ${fullTableName};
2353
+ DO $mastra_timestamps_trigger$
2354
+ BEGIN
2355
+ -- Recreating the trigger unconditionally would take an ACCESS EXCLUSIVE
2356
+ -- lock on the table (DROP TRIGGER does, even when nothing changes), and
2357
+ -- init runs on every process start. Skip when the trigger is already
2358
+ -- exactly what the CREATE below would produce.
2359
+ --
2360
+ -- tgtype 23 = ROW (1) | BEFORE (2) | INSERT (4) | UPDATE (16), so a trigger
2361
+ -- whose timing or events differ still falls through and gets rebuilt. The
2362
+ -- behaviour itself lives in the function, which is replaced above on every
2363
+ -- init, so an upgraded function body lands without touching the trigger.
2364
+ IF NOT EXISTS (
2365
+ SELECT 1
2366
+ FROM pg_catalog.pg_trigger tg
2367
+ JOIN pg_catalog.pg_class c ON c.oid = tg.tgrelid
2368
+ JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
2369
+ WHERE tg.tgname = ${`'${parsedTriggerName}'`}
2370
+ AND c.relname = ${`'${(0, _mastra_core_utils.parseSqlIdentifier)(tableName, "table name")}'`}
2371
+ AND n.nspname = ${schemaName ? `'${(0, _mastra_core_utils.parseSqlIdentifier)(schemaName, "schema name")}'` : `'public'`}
2372
+ AND NOT tg.tgisinternal
2373
+ AND tg.tgtype = 23
2374
+ AND tg.tgfoid = '${functionName}()'::regprocedure
2375
+ ) THEN
2376
+ DROP TRIGGER IF EXISTS ${triggerName} ON ${fullTableName};
2276
2377
 
2277
- CREATE TRIGGER ${triggerName}
2278
- BEFORE INSERT OR UPDATE ON ${fullTableName}
2279
- FOR EACH ROW
2280
- EXECUTE FUNCTION ${functionName}();`;
2378
+ CREATE TRIGGER ${triggerName}
2379
+ BEFORE INSERT OR UPDATE ON ${fullTableName}
2380
+ FOR EACH ROW
2381
+ EXECUTE FUNCTION ${functionName}();
2382
+ END IF;
2383
+ END
2384
+ $mastra_timestamps_trigger$;`;
2281
2385
  }
2282
2386
  const schemaSetupRegistry = /* @__PURE__ */ new Map();
2283
2387
  /**
@@ -2304,6 +2408,99 @@ var PgDB = class extends _mastra_core_base.MastraBase {
2304
2408
  this.skipDefaultIndexes = config.skipDefaultIndexes;
2305
2409
  }
2306
2410
  /**
2411
+ * Catalog snapshot for the current init window, or `null` outside it.
2412
+ *
2413
+ * When non-null, the init-path methods below answer existence questions from
2414
+ * it instead of round-tripping to the server, and record the objects they
2415
+ * create so later callers in the same init see them. See
2416
+ * {@link SchemaSnapshot} for why it is scoped to init only.
2417
+ */
2418
+ get schemaSnapshot() {
2419
+ return getSchemaSnapshot(this.client, this.schemaName);
2420
+ }
2421
+ /**
2422
+ * Whether the snapshot proves `generateTableSQL` would be a no-op for this
2423
+ * table — i.e. the CREATE statement can be skipped.
2424
+ *
2425
+ * For most tables that is just "the table exists". `workflow_snapshot` is the
2426
+ * exception: its generated SQL also carries a DO block that back-fills the
2427
+ * `(workflow_name, run_id)` unique constraint and promotes it to the table's
2428
+ * replica identity, so a table created by an older version still needs the
2429
+ * statement to run.
2430
+ */
2431
+ snapshotShowsTableConverged(snapshot, tableName) {
2432
+ if (!snapshot.tables.has(tableName)) return false;
2433
+ if (tableName === _mastra_core_storage.TABLE_WORKFLOW_SNAPSHOT) {
2434
+ const constraintName = buildConstraintName({
2435
+ baseName: "mastra_workflow_snapshot_workflow_name_run_id_key",
2436
+ schemaName: this.schemaName ? (0, _mastra_core_utils.parseSqlIdentifier)(this.schemaName, "schema name") : void 0
2437
+ }).toLowerCase();
2438
+ return snapshot.indexes.has(constraintName) && snapshot.replicaIdentityIndexes.has(constraintName);
2439
+ }
2440
+ return true;
2441
+ }
2442
+ /** Column set for `tableName` in the snapshot, created empty if absent. */
2443
+ snapshotColumns(snapshot, tableName) {
2444
+ let columns = snapshot.columns.get(tableName);
2445
+ if (!columns) {
2446
+ columns = /* @__PURE__ */ new Set();
2447
+ snapshot.columns.set(tableName, columns);
2448
+ }
2449
+ return columns;
2450
+ }
2451
+ /**
2452
+ * Records an out-of-band `ALTER TABLE … RENAME TO` in the init snapshot.
2453
+ *
2454
+ * Init-time migrations that issue raw DDL on `this.client` (instead of going
2455
+ * through createTable/alterTable/createIndex, which maintain the snapshot
2456
+ * themselves) MUST report it through these `note*` methods. A snapshot that
2457
+ * still lists a renamed-away table makes a later createTable() in the same
2458
+ * init skip the rebuild the migration depends on — stranding data. No-op
2459
+ * outside the init window.
2460
+ *
2461
+ * Indexes riding along with a rename keep their names, so the snapshot's
2462
+ * index set stays accurate without changes here.
2463
+ */
2464
+ noteTableRenamed(oldName, newName) {
2465
+ const snapshot = this.schemaSnapshot;
2466
+ if (snapshot) {
2467
+ if (snapshot.tables.delete(oldName)) snapshot.tables.add(newName);
2468
+ const columns = snapshot.columns.get(oldName);
2469
+ if (columns) {
2470
+ snapshot.columns.delete(oldName);
2471
+ snapshot.columns.set(newName, columns);
2472
+ }
2473
+ }
2474
+ this.tableColumnsCache.delete(oldName);
2475
+ this.tableColumnsCache.delete(newName);
2476
+ }
2477
+ /**
2478
+ * Records an out-of-band `DROP TABLE` in the init snapshot. See
2479
+ * {@link noteTableRenamed} for why raw-DDL migrations must call this.
2480
+ *
2481
+ * The dropped table's indexes vanish with it, but the snapshot's flat index
2482
+ * set cannot map names back to tables. Stale entries only make a later
2483
+ * createIndex() skip a recreate until the next init re-reads the catalog —
2484
+ * the same self-healing bound the rest of the snapshot design accepts.
2485
+ */
2486
+ noteTableDropped(tableName) {
2487
+ const snapshot = this.schemaSnapshot;
2488
+ if (snapshot) {
2489
+ snapshot.tables.delete(tableName);
2490
+ snapshot.columns.delete(tableName);
2491
+ }
2492
+ this.tableColumnsCache.delete(tableName);
2493
+ }
2494
+ /**
2495
+ * Records an out-of-band `ALTER TABLE … ADD COLUMN` in the init snapshot.
2496
+ * See {@link noteTableRenamed} for why raw-DDL migrations must call this.
2497
+ */
2498
+ noteColumnAdded(tableName, column) {
2499
+ const snapshot = this.schemaSnapshot;
2500
+ if (snapshot) this.snapshotColumns(snapshot, tableName).add(column);
2501
+ this.tableColumnsCache.delete(tableName);
2502
+ }
2503
+ /**
2307
2504
  * Gets the set of column names that actually exist in the database table.
2308
2505
  * Results are cached; the cache is invalidated when alterTable() adds new columns.
2309
2506
  */
@@ -2330,6 +2527,12 @@ var PgDB = class extends _mastra_core_base.MastraBase {
2330
2527
  }
2331
2528
  async hasColumn(table, column) {
2332
2529
  const schema = this.schemaName || "public";
2530
+ const snapshot = this.schemaSnapshot;
2531
+ if (snapshot) {
2532
+ const columns = snapshot.columns.get(table);
2533
+ if (!columns) return false;
2534
+ return columns.has(column) || columns.has(column.toLowerCase());
2535
+ }
2333
2536
  return !!await this.client.oneOrNone(`SELECT 1 FROM information_schema.columns WHERE table_schema = $1 AND table_name = $2 AND (column_name = $3 OR column_name = $4)`, [
2334
2537
  schema,
2335
2538
  table,
@@ -2368,6 +2571,14 @@ var PgDB = class extends _mastra_core_base.MastraBase {
2368
2571
  if (!this.schemaName) return;
2369
2572
  let registryEntry = schemaSetupRegistry.get(this.schemaName);
2370
2573
  if (registryEntry?.complete) return;
2574
+ const snapshot = this.schemaSnapshot;
2575
+ if (snapshot && snapshot.tables.size > 0) {
2576
+ schemaSetupRegistry.set(this.schemaName, {
2577
+ promise: null,
2578
+ complete: true
2579
+ });
2580
+ return;
2581
+ }
2371
2582
  const quotedSchemaName = getSchemaName$6(this.schemaName);
2372
2583
  if (!registryEntry?.promise) {
2373
2584
  const schemaNameCapture = this.schemaName;
@@ -2472,16 +2683,28 @@ var PgDB = class extends _mastra_core_base.MastraBase {
2472
2683
  try {
2473
2684
  const timeZColumnNames = Object.entries(schema).filter(([_, def]) => def.type === "timestamp").map(([name]) => name);
2474
2685
  if (this.schemaName) await this.setupSchema();
2475
- const sql = generateTableSQL({
2476
- tableName,
2477
- schema,
2478
- schemaName: this.schemaName,
2479
- compositePrimaryKey
2480
- });
2481
- try {
2482
- await this.client.none(sql);
2483
- } catch (error) {
2484
- if (!isDuplicateRelationError(error)) throw error;
2686
+ const snapshot = this.schemaSnapshot;
2687
+ if (!snapshot || !this.snapshotShowsTableConverged(snapshot, tableName)) {
2688
+ const sql = generateTableSQL({
2689
+ tableName,
2690
+ schema,
2691
+ schemaName: this.schemaName,
2692
+ compositePrimaryKey
2693
+ });
2694
+ try {
2695
+ await this.client.none(sql);
2696
+ } catch (error) {
2697
+ if (!isDuplicateRelationError(error)) throw error;
2698
+ }
2699
+ if (snapshot) {
2700
+ snapshot.tables.add(tableName);
2701
+ const created = this.snapshotColumns(snapshot, tableName);
2702
+ for (const [name, def] of Object.entries(schema)) {
2703
+ const parsedName = (0, _mastra_core_utils.parseSqlIdentifier)(name, "column name");
2704
+ created.add(parsedName);
2705
+ if (def.type === "timestamp") created.add(`${parsedName}Z`);
2706
+ }
2707
+ }
2485
2708
  }
2486
2709
  await this.alterTable({
2487
2710
  tableName,
@@ -2547,10 +2770,12 @@ MIGRATION REQUIRED: Duplicate spans detected in ${duplicateInfo.tableName}\n====
2547
2770
  const sqlType = mapToSqlType(columnDef.type);
2548
2771
  const alterSql = `ALTER TABLE ${fullTableName} ADD COLUMN IF NOT EXISTS "${parsedColumnName}" ${sqlType} ${columnDef.nullable ? "" : "NOT NULL"} ${!columnDef.nullable ? this.getDefaultValue(columnDef.type) : ""}`.trim();
2549
2772
  await this.client.none(alterSql);
2773
+ this.noteColumnAdded(_mastra_core_storage.TABLE_SPANS, columnName);
2550
2774
  this.logger?.debug?.(`Added column '${columnName}' to ${fullTableName}`);
2551
2775
  if (sqlType === "TIMESTAMP") {
2552
2776
  const timestampZSql = `ALTER TABLE ${fullTableName} ADD COLUMN IF NOT EXISTS "${parsedColumnName}Z" TIMESTAMPTZ DEFAULT NOW()`.trim();
2553
2777
  await this.client.none(timestampZSql);
2778
+ this.noteColumnAdded(_mastra_core_storage.TABLE_SPANS, `${columnName}Z`);
2554
2779
  this.logger?.debug?.(`Added timezone column '${columnName}Z' to ${fullTableName}`);
2555
2780
  }
2556
2781
  }
@@ -2559,6 +2784,7 @@ MIGRATION REQUIRED: Duplicate spans detected in ${duplicateInfo.tableName}\n====
2559
2784
  if (!await this.hasColumn(_mastra_core_storage.TABLE_SPANS, tzColumnName)) {
2560
2785
  const timestampZSql = `ALTER TABLE ${fullTableName} ADD COLUMN IF NOT EXISTS "${(0, _mastra_core_utils.parseSqlIdentifier)(tzColumnName, "column name")}" TIMESTAMPTZ DEFAULT NOW()`.trim();
2561
2786
  await this.client.none(timestampZSql);
2787
+ this.noteColumnAdded(_mastra_core_storage.TABLE_SPANS, tzColumnName);
2562
2788
  this.logger?.debug?.(`Added timezone column '${tzColumnName}' to ${fullTableName}`);
2563
2789
  }
2564
2790
  }
@@ -2681,6 +2907,12 @@ MIGRATION REQUIRED: Duplicate spans detected in ${duplicateInfo.tableName}\n====
2681
2907
  schemaName: (this.schemaName ? (0, _mastra_core_utils.parseSqlIdentifier)(this.schemaName, "schema name") : "") || void 0
2682
2908
  });
2683
2909
  const schemaFilter = this.schemaName || "public";
2910
+ const snapshot = this.schemaSnapshot;
2911
+ if (snapshot) return snapshot.primaryKeyIndexes.has(constraintName.toLowerCase());
2912
+ return this.spansPrimaryKeyExistsLive(constraintName, schemaFilter);
2913
+ }
2914
+ /** Live-catalog variant of {@link spansPrimaryKeyExists}, bypassing the snapshot. */
2915
+ async spansPrimaryKeyExistsLive(constraintName, schemaFilter) {
2684
2916
  return (await this.client.oneOrNone(`SELECT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = lower($1) AND connamespace = (SELECT oid FROM pg_namespace WHERE nspname = $2)) as exists`, [constraintName, schemaFilter]))?.exists ?? false;
2685
2917
  }
2686
2918
  /**
@@ -2711,10 +2943,12 @@ MIGRATION REQUIRED: Duplicate spans detected in ${duplicateInfo.tableName}\n====
2711
2943
  ADD CONSTRAINT ${constraintName}
2712
2944
  PRIMARY KEY ("traceId", "spanId")
2713
2945
  `);
2946
+ this.schemaSnapshot?.primaryKeyIndexes.add(constraintName.toLowerCase());
2714
2947
  this.logger?.info?.(`Added PRIMARY KEY constraint ${constraintName} to ${fullTableName}`);
2715
2948
  } catch (error) {
2716
2949
  if (isDuplicateRelationError(error)) {
2717
- if (await this.spansPrimaryKeyExists()) {
2950
+ if (await this.spansPrimaryKeyExistsLive(constraintName, schemaFilter)) {
2951
+ this.schemaSnapshot?.primaryKeyIndexes.add(constraintName.toLowerCase());
2718
2952
  this.logger?.debug?.(`PRIMARY KEY constraint ${constraintName} was created by another process`);
2719
2953
  return;
2720
2954
  }
@@ -2796,16 +3030,25 @@ MIGRATION REQUIRED: Duplicate spans detected in ${duplicateInfo.tableName}\n====
2796
3030
  indexName: tableName,
2797
3031
  schemaName: getSchemaName$6(this.schemaName)
2798
3032
  });
3033
+ const snapshot = this.schemaSnapshot;
3034
+ const knownColumns = snapshot ? this.snapshotColumns(snapshot, tableName) : null;
2799
3035
  try {
2800
3036
  for (const columnName of ifNotExists) if (schema[columnName]) {
2801
3037
  const columnDef = schema[columnName];
2802
3038
  const parsedColumnName = (0, _mastra_core_utils.parseSqlIdentifier)(columnName, "column name");
2803
3039
  const sqlType = mapToSqlType(columnDef.type);
2804
3040
  const alterSql = `ALTER TABLE ${fullTableName} ADD COLUMN IF NOT EXISTS "${parsedColumnName}" ${sqlType} ${columnDef.nullable ? "" : "NOT NULL"} ${!columnDef.nullable ? this.getDefaultValue(columnDef.type) : ""}`.trim();
2805
- await this.client.none(alterSql);
3041
+ if (!knownColumns?.has(parsedColumnName)) {
3042
+ await this.client.none(alterSql);
3043
+ knownColumns?.add(parsedColumnName);
3044
+ }
2806
3045
  if (sqlType === "TIMESTAMP") {
2807
- const timestampZSql = `ALTER TABLE ${fullTableName} ADD COLUMN IF NOT EXISTS "${parsedColumnName}Z" TIMESTAMPTZ DEFAULT NOW()`.trim();
2808
- await this.client.none(timestampZSql);
3046
+ const tzColumnName = `${parsedColumnName}Z`;
3047
+ if (!knownColumns?.has(tzColumnName)) {
3048
+ const timestampZSql = `ALTER TABLE ${fullTableName} ADD COLUMN IF NOT EXISTS "${tzColumnName}" TIMESTAMPTZ DEFAULT NOW()`.trim();
3049
+ await this.client.none(timestampZSql);
3050
+ knownColumns?.add(tzColumnName);
3051
+ }
2809
3052
  }
2810
3053
  this.logger?.debug?.(`Ensured column ${parsedColumnName} exists in table ${fullTableName}`);
2811
3054
  }
@@ -2891,7 +3134,10 @@ MIGRATION REQUIRED: Duplicate spans detected in ${duplicateInfo.tableName}\n====
2891
3134
  indexName: table,
2892
3135
  schemaName: getSchemaName$6(this.schemaName)
2893
3136
  });
2894
- if (await this.client.oneOrNone(`SELECT 1 FROM pg_indexes
3137
+ const snapshot = this.schemaSnapshot;
3138
+ if (snapshot) {
3139
+ if (snapshot.indexes.has(name)) return;
3140
+ } else if (await this.client.oneOrNone(`SELECT 1 FROM pg_indexes
2895
3141
  WHERE indexname = $1
2896
3142
  AND schemaname = $2`, [name, schemaName])) return;
2897
3143
  const uniqueStr = unique ? "UNIQUE " : "";
@@ -2913,6 +3159,7 @@ MIGRATION REQUIRED: Duplicate spans detected in ${duplicateInfo.tableName}\n====
2913
3159
  if (storage && Object.keys(storage).length > 0) withStr = ` WITH (${Object.entries(storage).map(([key, value]) => `${key} = ${value}`).join(", ")})`;
2914
3160
  const sql = `CREATE ${uniqueStr}INDEX ${concurrentStr}${`"${(0, _mastra_core_utils.parseSqlIdentifier)(name, "index name")}"`} ON ${fullTableName} ${methodStr}(${columnsStr})${withStr}${tablespaceStr}${whereStr}`;
2915
3161
  await this.client.none(sql);
3162
+ snapshot?.indexes.add(name);
2916
3163
  } catch (error) {
2917
3164
  if (error instanceof Error && error.message.includes("CONCURRENTLY")) {
2918
3165
  const retryOptions = {
@@ -2932,15 +3179,34 @@ MIGRATION REQUIRED: Duplicate spans detected in ${duplicateInfo.tableName}\n====
2932
3179
  }, error);
2933
3180
  }
2934
3181
  }
3182
+ /**
3183
+ * Runs a caller-built `CREATE INDEX IF NOT EXISTS` statement, unless the init
3184
+ * snapshot already proves `indexName` exists.
3185
+ *
3186
+ * `createIndex` covers the indexes described by {@link CreateIndexOptions};
3187
+ * this is for the two init paths that hand-write their statement (a partial
3188
+ * or otherwise non-standard index) and would otherwise send a no-op DDL on
3189
+ * every warm init.
3190
+ */
3191
+ async createIndexFromStatement(indexName, sql) {
3192
+ const snapshot = this.schemaSnapshot;
3193
+ if (snapshot?.indexes.has(indexName)) return;
3194
+ await this.client.none(sql);
3195
+ snapshot?.indexes.add(indexName);
3196
+ }
2935
3197
  async dropIndex(indexName) {
2936
3198
  try {
2937
3199
  const schemaName = this.schemaName || "public";
2938
- if (!await this.client.oneOrNone(`SELECT 1 FROM pg_indexes
3200
+ const snapshot = this.schemaSnapshot;
3201
+ if (snapshot) {
3202
+ if (!snapshot.indexes.has(indexName)) return;
3203
+ } else if (!await this.client.oneOrNone(`SELECT 1 FROM pg_indexes
2939
3204
  WHERE indexname = $1
2940
3205
  AND schemaname = $2`, [indexName, schemaName])) return;
2941
3206
  const quotedIndexName = `"${(0, _mastra_core_utils.parseSqlIdentifier)(indexName, "index name")}"`;
2942
3207
  const sql = `DROP INDEX IF EXISTS ${getSchemaName$6(this.schemaName)}.${quotedIndexName}`;
2943
3208
  await this.client.none(sql);
3209
+ snapshot?.indexes.delete(indexName);
2944
3210
  } catch (error) {
2945
3211
  throw new _mastra_core_error.MastraError({
2946
3212
  id: (0, _mastra_core_storage.createStorageErrorId)("PG", "INDEX_DROP", "FAILED"),
@@ -3437,7 +3703,9 @@ var AgentsPG = class AgentsPG extends _mastra_core_storage.AgentsStorage {
3437
3703
  });
3438
3704
  if (await this.#db.hasColumn(_mastra_core_storage.TABLE_AGENTS, "name")) {
3439
3705
  await this.#db.client.none(`ALTER TABLE ${fullTableName} RENAME TO "${_mastra_core_storage.TABLE_AGENTS}_legacy"`);
3706
+ this.#db.noteTableRenamed(_mastra_core_storage.TABLE_AGENTS, `${_mastra_core_storage.TABLE_AGENTS}_legacy`);
3440
3707
  await this.#db.client.none(`DROP TABLE IF EXISTS ${fullVersionsTableName}`);
3708
+ this.#db.noteTableDropped(_mastra_core_storage.TABLE_AGENT_VERSIONS);
3441
3709
  }
3442
3710
  if (!await this.#db.hasColumn(`${_mastra_core_storage.TABLE_AGENTS}_legacy`, "name")) return;
3443
3711
  const oldAgents = await this.#db.client.manyOrNone(`SELECT * FROM ${legacyTableName}`);
@@ -3494,6 +3762,7 @@ var AgentsPG = class AgentsPG extends _mastra_core_storage.AgentsStorage {
3494
3762
  ]);
3495
3763
  }
3496
3764
  await this.#db.client.none(`DROP TABLE IF EXISTS ${legacyTableName}`);
3765
+ this.#db.noteTableDropped(`${_mastra_core_storage.TABLE_AGENTS}_legacy`);
3497
3766
  }
3498
3767
  /**
3499
3768
  * Migrates the agent_versions table from the old snapshot-based schema (single `snapshot` JSON column)
@@ -3511,7 +3780,9 @@ var AgentsPG = class AgentsPG extends _mastra_core_storage.AgentsStorage {
3511
3780
  schemaName: getSchemaName$5(this.#schema)
3512
3781
  });
3513
3782
  await this.#db.client.none(`DROP TABLE IF EXISTS ${fullVersionsTableName}`);
3783
+ this.#db.noteTableDropped(_mastra_core_storage.TABLE_AGENT_VERSIONS);
3514
3784
  await this.#db.client.none(`DROP TABLE IF EXISTS ${legacyTableName}`);
3785
+ this.#db.noteTableDropped(`${_mastra_core_storage.TABLE_AGENTS}_legacy`);
3515
3786
  }
3516
3787
  /**
3517
3788
  * Migrates the tools field from string[] format to JSONB format { "tool-key": { "description": "..." } }.
@@ -5027,6 +5298,7 @@ var DatasetsPG = class DatasetsPG extends _mastra_core_storage.DatasetsStorage {
5027
5298
  await this.#addColumnIfNotExists(_mastra_core_storage.TABLE_DATASET_ITEMS, "organizationId", "TEXT");
5028
5299
  await this.#addColumnIfNotExists(_mastra_core_storage.TABLE_DATASET_ITEMS, "projectId", "TEXT");
5029
5300
  await this.#addColumnIfNotExists(_mastra_core_storage.TABLE_DATASET_ITEMS, "toolMocks", "JSONB");
5301
+ await this.#addColumnIfNotExists(_mastra_core_storage.TABLE_DATASET_ITEMS, "unmockedToolPolicy", "TEXT");
5030
5302
  await this.#addColumnIfNotExists(_mastra_core_storage.TABLE_DATASET_ITEMS, "externalId", "TEXT");
5031
5303
  await this.createDefaultIndexes();
5032
5304
  await this.createCustomIndexes();
@@ -5038,6 +5310,7 @@ var DatasetsPG = class DatasetsPG extends _mastra_core_storage.DatasetsStorage {
5038
5310
  schemaName: getSchemaName$5(this.#schema)
5039
5311
  });
5040
5312
  await this.#db.client.none(`ALTER TABLE ${fullTableName} ADD COLUMN "${column}" ${sqlType}`);
5313
+ this.#db.noteColumnAdded(table, column);
5041
5314
  }
5042
5315
  }
5043
5316
  getDefaultIndexDefinitions() {
@@ -5148,6 +5421,7 @@ var DatasetsPG = class DatasetsPG extends _mastra_core_storage.DatasetsStorage {
5148
5421
  groundTruth: row.groundTruth ? (0, _mastra_core_storage.safelyParseJSON)(row.groundTruth) : void 0,
5149
5422
  expectedTrajectory: row.expectedTrajectory ? (0, _mastra_core_storage.safelyParseJSON)(row.expectedTrajectory) : void 0,
5150
5423
  toolMocks: row.toolMocks ? (0, _mastra_core_storage.safelyParseJSON)(row.toolMocks) : void 0,
5424
+ unmockedToolPolicy: row.unmockedToolPolicy ?? void 0,
5151
5425
  requestContext: row.requestContext ? (0, _mastra_core_storage.safelyParseJSON)(row.requestContext) : void 0,
5152
5426
  metadata: row.metadata ? (0, _mastra_core_storage.safelyParseJSON)(row.metadata) : void 0,
5153
5427
  source: row.source ? (0, _mastra_core_storage.safelyParseJSON)(row.source) : void 0,
@@ -5169,6 +5443,7 @@ var DatasetsPG = class DatasetsPG extends _mastra_core_storage.DatasetsStorage {
5169
5443
  groundTruth: row.groundTruth ? (0, _mastra_core_storage.safelyParseJSON)(row.groundTruth) : void 0,
5170
5444
  expectedTrajectory: row.expectedTrajectory ? (0, _mastra_core_storage.safelyParseJSON)(row.expectedTrajectory) : void 0,
5171
5445
  toolMocks: row.toolMocks ? (0, _mastra_core_storage.safelyParseJSON)(row.toolMocks) : void 0,
5446
+ unmockedToolPolicy: row.unmockedToolPolicy ?? void 0,
5172
5447
  requestContext: row.requestContext ? (0, _mastra_core_storage.safelyParseJSON)(row.requestContext) : void 0,
5173
5448
  metadata: row.metadata ? (0, _mastra_core_storage.safelyParseJSON)(row.metadata) : void 0,
5174
5449
  source: row.source ? (0, _mastra_core_storage.safelyParseJSON)(row.source) : void 0,
@@ -5500,7 +5775,7 @@ var DatasetsPG = class DatasetsPG extends _mastra_core_storage.DatasetsStorage {
5500
5775
  newVersion = row.version;
5501
5776
  parentOrganizationId = row.organizationId ?? null;
5502
5777
  parentProjectId = row.projectId ?? null;
5503
- await t.none(`INSERT INTO ${itemsTable} ("id","datasetId","datasetVersion","externalId","organizationId","projectId","validTo","isDeleted","input","groundTruth","expectedTrajectory","toolMocks","requestContext","metadata","source","createdAt","createdAtZ","updatedAt","updatedAtZ") VALUES ($1,$2,$3,$4,$5,$6,NULL,false,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17)`, [
5778
+ await t.none(`INSERT INTO ${itemsTable} ("id","datasetId","datasetVersion","externalId","organizationId","projectId","validTo","isDeleted","input","groundTruth","expectedTrajectory","toolMocks","unmockedToolPolicy","requestContext","metadata","source","createdAt","createdAtZ","updatedAt","updatedAtZ") VALUES ($1,$2,$3,$4,$5,$6,NULL,false,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18)`, [
5504
5779
  id,
5505
5780
  args.datasetId,
5506
5781
  newVersion,
@@ -5511,6 +5786,7 @@ var DatasetsPG = class DatasetsPG extends _mastra_core_storage.DatasetsStorage {
5511
5786
  jsonbArg(args.groundTruth),
5512
5787
  jsonbArg(args.expectedTrajectory),
5513
5788
  jsonbArg(args.toolMocks),
5789
+ args.unmockedToolPolicy ?? null,
5514
5790
  jsonbArg(args.requestContext),
5515
5791
  jsonbArg(args.metadata),
5516
5792
  jsonbArg(args.source),
@@ -5537,6 +5813,7 @@ var DatasetsPG = class DatasetsPG extends _mastra_core_storage.DatasetsStorage {
5537
5813
  groundTruth: args.groundTruth,
5538
5814
  expectedTrajectory: args.expectedTrajectory,
5539
5815
  toolMocks: args.toolMocks,
5816
+ unmockedToolPolicy: args.unmockedToolPolicy,
5540
5817
  requestContext: args.requestContext,
5541
5818
  metadata: args.metadata,
5542
5819
  source: args.source,
@@ -5590,6 +5867,7 @@ var DatasetsPG = class DatasetsPG extends _mastra_core_storage.DatasetsStorage {
5590
5867
  const mergedGroundTruth = args.groundTruth !== void 0 ? args.groundTruth : existing.groundTruth;
5591
5868
  const mergedExpectedTrajectory = args.expectedTrajectory !== void 0 ? args.expectedTrajectory : existing.expectedTrajectory;
5592
5869
  const mergedToolMocks = args.toolMocks !== void 0 ? args.toolMocks : existing.toolMocks;
5870
+ const mergedUnmockedToolPolicy = args.unmockedToolPolicy !== void 0 ? args.unmockedToolPolicy : existing.unmockedToolPolicy;
5593
5871
  const mergedRequestContext = args.requestContext !== void 0 ? args.requestContext : existing.requestContext;
5594
5872
  const mergedMetadata = args.metadata !== void 0 ? args.metadata : existing.metadata;
5595
5873
  const mergedSource = args.source !== void 0 ? args.source : existing.source;
@@ -5602,7 +5880,7 @@ var DatasetsPG = class DatasetsPG extends _mastra_core_storage.DatasetsStorage {
5602
5880
  parentOrganizationId = row.organizationId ?? null;
5603
5881
  parentProjectId = row.projectId ?? null;
5604
5882
  await t.none(`UPDATE ${itemsTable} SET "validTo" = $1 WHERE "id" = $2 AND "validTo" IS NULL AND "isDeleted" = false`, [newVersion, args.id]);
5605
- await t.none(`INSERT INTO ${itemsTable} ("id","datasetId","datasetVersion","externalId","organizationId","projectId","validTo","isDeleted","input","groundTruth","expectedTrajectory","toolMocks","requestContext","metadata","source","createdAt","createdAtZ","updatedAt","updatedAtZ") VALUES ($1,$2,$3,$4,$5,$6,NULL,false,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17)`, [
5883
+ await t.none(`INSERT INTO ${itemsTable} ("id","datasetId","datasetVersion","externalId","organizationId","projectId","validTo","isDeleted","input","groundTruth","expectedTrajectory","toolMocks","unmockedToolPolicy","requestContext","metadata","source","createdAt","createdAtZ","updatedAt","updatedAtZ") VALUES ($1,$2,$3,$4,$5,$6,NULL,false,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18)`, [
5606
5884
  args.id,
5607
5885
  args.datasetId,
5608
5886
  newVersion,
@@ -5613,6 +5891,7 @@ var DatasetsPG = class DatasetsPG extends _mastra_core_storage.DatasetsStorage {
5613
5891
  jsonbArg(mergedGroundTruth),
5614
5892
  jsonbArg(mergedExpectedTrajectory),
5615
5893
  jsonbArg(mergedToolMocks),
5894
+ mergedUnmockedToolPolicy ?? null,
5616
5895
  jsonbArg(mergedRequestContext),
5617
5896
  jsonbArg(mergedMetadata),
5618
5897
  jsonbArg(mergedSource),
@@ -5638,6 +5917,7 @@ var DatasetsPG = class DatasetsPG extends _mastra_core_storage.DatasetsStorage {
5638
5917
  groundTruth: mergedGroundTruth,
5639
5918
  expectedTrajectory: mergedExpectedTrajectory,
5640
5919
  toolMocks: mergedToolMocks,
5920
+ unmockedToolPolicy: mergedUnmockedToolPolicy,
5641
5921
  requestContext: mergedRequestContext,
5642
5922
  metadata: mergedMetadata,
5643
5923
  source: mergedSource,
@@ -5686,7 +5966,7 @@ var DatasetsPG = class DatasetsPG extends _mastra_core_storage.DatasetsStorage {
5686
5966
  const parentOrganizationId = row.organizationId ?? null;
5687
5967
  const parentProjectId = row.projectId ?? null;
5688
5968
  await t.none(`UPDATE ${itemsTable} SET "validTo" = $1 WHERE "id" = $2 AND "validTo" IS NULL AND "isDeleted" = false`, [newVersion, id]);
5689
- await t.none(`INSERT INTO ${itemsTable} ("id","datasetId","datasetVersion","externalId","organizationId","projectId","validTo","isDeleted","input","groundTruth","expectedTrajectory","toolMocks","requestContext","metadata","source","createdAt","createdAtZ","updatedAt","updatedAtZ") VALUES ($1,$2,$3,$4,$5,$6,NULL,true,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17)`, [
5969
+ await t.none(`INSERT INTO ${itemsTable} ("id","datasetId","datasetVersion","externalId","organizationId","projectId","validTo","isDeleted","input","groundTruth","expectedTrajectory","toolMocks","unmockedToolPolicy","requestContext","metadata","source","createdAt","createdAtZ","updatedAt","updatedAtZ") VALUES ($1,$2,$3,$4,$5,$6,NULL,true,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18)`, [
5690
5970
  id,
5691
5971
  datasetId,
5692
5972
  newVersion,
@@ -5697,6 +5977,7 @@ var DatasetsPG = class DatasetsPG extends _mastra_core_storage.DatasetsStorage {
5697
5977
  jsonbArg(existing.groundTruth),
5698
5978
  jsonbArg(existing.expectedTrajectory),
5699
5979
  jsonbArg(existing.toolMocks),
5980
+ existing.unmockedToolPolicy ?? null,
5700
5981
  jsonbArg(existing.requestContext),
5701
5982
  jsonbArg(existing.metadata),
5702
5983
  jsonbArg(existing.source),
@@ -5756,7 +6037,7 @@ var DatasetsPG = class DatasetsPG extends _mastra_core_storage.DatasetsStorage {
5756
6037
  const nowIso = now.toISOString();
5757
6038
  await t.none(`UPDATE ${datasetsTable} SET "version" = $2 WHERE "id" = $1`, [input.datasetId, newVersion]);
5758
6039
  for (const { id, item } of plan.inserts) {
5759
- await t.none(`INSERT INTO ${itemsTable} ("id","datasetId","datasetVersion","externalId","organizationId","projectId","validTo","isDeleted","input","groundTruth","expectedTrajectory","toolMocks","requestContext","metadata","source","createdAt","createdAtZ","updatedAt","updatedAtZ") VALUES ($1,$2,$3,$4,$5,$6,NULL,false,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17)`, [
6040
+ await t.none(`INSERT INTO ${itemsTable} ("id","datasetId","datasetVersion","externalId","organizationId","projectId","validTo","isDeleted","input","groundTruth","expectedTrajectory","toolMocks","unmockedToolPolicy","requestContext","metadata","source","createdAt","createdAtZ","updatedAt","updatedAtZ") VALUES ($1,$2,$3,$4,$5,$6,NULL,false,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18)`, [
5760
6041
  id,
5761
6042
  input.datasetId,
5762
6043
  newVersion,
@@ -5767,6 +6048,7 @@ var DatasetsPG = class DatasetsPG extends _mastra_core_storage.DatasetsStorage {
5767
6048
  jsonbArg(item.groundTruth),
5768
6049
  jsonbArg(item.expectedTrajectory),
5769
6050
  jsonbArg(item.toolMocks),
6051
+ item.unmockedToolPolicy ?? null,
5770
6052
  jsonbArg(item.requestContext),
5771
6053
  jsonbArg(item.metadata),
5772
6054
  jsonbArg(item.source),
@@ -5786,6 +6068,7 @@ var DatasetsPG = class DatasetsPG extends _mastra_core_storage.DatasetsStorage {
5786
6068
  groundTruth: item.groundTruth,
5787
6069
  expectedTrajectory: item.expectedTrajectory,
5788
6070
  toolMocks: item.toolMocks,
6071
+ unmockedToolPolicy: item.unmockedToolPolicy,
5789
6072
  requestContext: item.requestContext,
5790
6073
  metadata: item.metadata,
5791
6074
  source: item.source,
@@ -5848,7 +6131,7 @@ var DatasetsPG = class DatasetsPG extends _mastra_core_storage.DatasetsStorage {
5848
6131
  const newVersion = (await t.one(`UPDATE ${datasetsTable} SET "version" = "version" + 1 WHERE "id" = $1 RETURNING "version"`, [input.datasetId])).version;
5849
6132
  for (const item of currentItems) {
5850
6133
  await t.none(`UPDATE ${itemsTable} SET "validTo" = $1 WHERE "id" = $2 AND "validTo" IS NULL AND "isDeleted" = false`, [newVersion, item.id]);
5851
- await t.none(`INSERT INTO ${itemsTable} ("id","datasetId","datasetVersion","externalId","organizationId","projectId","validTo","isDeleted","input","groundTruth","expectedTrajectory","toolMocks","requestContext","metadata","source","createdAt","createdAtZ","updatedAt","updatedAtZ") VALUES ($1,$2,$3,$4,$5,$6,NULL,true,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17)`, [
6134
+ await t.none(`INSERT INTO ${itemsTable} ("id","datasetId","datasetVersion","externalId","organizationId","projectId","validTo","isDeleted","input","groundTruth","expectedTrajectory","toolMocks","unmockedToolPolicy","requestContext","metadata","source","createdAt","createdAtZ","updatedAt","updatedAtZ") VALUES ($1,$2,$3,$4,$5,$6,NULL,true,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18)`, [
5852
6135
  item.id,
5853
6136
  input.datasetId,
5854
6137
  newVersion,
@@ -5859,6 +6142,7 @@ var DatasetsPG = class DatasetsPG extends _mastra_core_storage.DatasetsStorage {
5859
6142
  jsonbArg(item.groundTruth),
5860
6143
  jsonbArg(item.expectedTrajectory),
5861
6144
  jsonbArg(item.toolMocks),
6145
+ item.unmockedToolPolicy ?? null,
5862
6146
  jsonbArg(item.requestContext),
5863
6147
  jsonbArg(item.metadata),
5864
6148
  jsonbArg(item.source),
@@ -6153,6 +6437,7 @@ var ExperimentsPG = class ExperimentsPG extends _mastra_core_storage.Experiments
6153
6437
  ifNotExists: [
6154
6438
  "status",
6155
6439
  "tags",
6440
+ "comment",
6156
6441
  "toolMockReport",
6157
6442
  "organizationId",
6158
6443
  "projectId"
@@ -6330,6 +6615,7 @@ var ExperimentsPG = class ExperimentsPG extends _mastra_core_storage.Experiments
6330
6615
  traceId: row.traceId ?? null,
6331
6616
  status: row.status ?? null,
6332
6617
  tags: row.tags ? (0, _mastra_core_storage.safelyParseJSON)(row.tags) : null,
6618
+ comment: row.comment ?? null,
6333
6619
  toolMockReport: row.toolMockReport ? (0, _mastra_core_storage.safelyParseJSON)(row.toolMockReport) : null,
6334
6620
  createdAt: (0, _mastra_core_storage.ensureDate)(row.createdAtZ || row.createdAt)
6335
6621
  };
@@ -6655,6 +6941,10 @@ var ExperimentsPG = class ExperimentsPG extends _mastra_core_storage.Experiments
6655
6941
  setClauses.push(`"tags" = $${paramIndex++}`);
6656
6942
  values.push(JSON.stringify(input.tags));
6657
6943
  }
6944
+ if (input.comment !== void 0) {
6945
+ setClauses.push(`"comment" = $${paramIndex++}`);
6946
+ values.push(input.comment);
6947
+ }
6658
6948
  if (setClauses.length === 0) {
6659
6949
  const existing = await this.getExperimentResultById({ id: input.id });
6660
6950
  if (!existing) throw new _mastra_core_error.MastraError({
@@ -6890,7 +7180,7 @@ var FavoritesPG = class FavoritesPG extends _mastra_core_storage.FavoritesStorag
6890
7180
  indexName: _mastra_core_storage.TABLE_FAVORITES,
6891
7181
  schemaName: getSchemaName$5(this.#schema)
6892
7182
  });
6893
- await this.#db.client.none(`CREATE INDEX IF NOT EXISTS idx_favorites_entity ON ${fullTableName} ("entityType", "entityId")`);
7183
+ await this.#db.createIndexFromStatement("idx_favorites_entity", `CREATE INDEX IF NOT EXISTS idx_favorites_entity ON ${fullTableName} ("entityType", "entityId")`);
6894
7184
  }
6895
7185
  async dangerouslyClearAll() {
6896
7186
  const fullTableName = getTableName$5({
@@ -8386,7 +8676,7 @@ var MemoryPG = class MemoryPG extends _mastra_core_storage.MemoryStorage {
8386
8676
  indexName: OM_TABLE,
8387
8677
  schemaName: getSchemaName$3(this.#schema)
8388
8678
  });
8389
- await this.#db.client.none(`CREATE INDEX IF NOT EXISTS idx_om_lookup_key ON ${omTableName} ("lookupKey")`);
8679
+ await this.#db.createIndexFromStatement("idx_om_lookup_key", `CREATE INDEX IF NOT EXISTS idx_om_lookup_key ON ${omTableName} ("lookupKey")`);
8390
8680
  }
8391
8681
  await this.createDefaultIndexes();
8392
8682
  await this.createCustomIndexes();
@@ -20107,6 +20397,7 @@ var PostgresStore = class extends _mastra_core_storage.MastraCompositeStore {
20107
20397
  pinnedClient = await this.#pool.connect();
20108
20398
  const pinned = new PinnedClientAdapter(this.#pool, pinnedClient);
20109
20399
  this.#db.pin(pinned);
20400
+ this.#db.setSchemaSnapshot(await loadSchemaSnapshot(pinned, this.schema));
20110
20401
  await super.init();
20111
20402
  this.isInitialized = true;
20112
20403
  } catch (error) {
@@ -20118,6 +20409,7 @@ var PostgresStore = class extends _mastra_core_storage.MastraCompositeStore {
20118
20409
  category: _mastra_core_error.ErrorCategory.THIRD_PARTY
20119
20410
  }, error);
20120
20411
  } finally {
20412
+ this.#db.setSchemaSnapshot(null);
20121
20413
  if (pinnedClient) {
20122
20414
  this.#db.unpin();
20123
20415
  pinnedClient.release();