@mastra/pg 0.2.10-alpha.3 → 0.2.10-alpha.5

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.
@@ -1,8 +1,10 @@
1
1
  import { randomUUID } from 'crypto';
2
2
  import type { MetricResult } from '@mastra/core/eval';
3
+ import type { MessageType } from '@mastra/core/memory';
3
4
  import { TABLE_WORKFLOW_SNAPSHOT, TABLE_MESSAGES, TABLE_THREADS, TABLE_EVALS } from '@mastra/core/storage';
4
5
  import type { WorkflowRunState } from '@mastra/core/workflows';
5
- import { describe, it, expect, beforeAll, beforeEach, afterAll } from 'vitest';
6
+ import pgPromise from 'pg-promise';
7
+ import { describe, it, expect, beforeAll, beforeEach, afterAll, afterEach } from 'vitest';
6
8
 
7
9
  import { PostgresStore } from '.';
8
10
  import type { PostgresConfig } from '.';
@@ -15,6 +17,8 @@ const TEST_CONFIG: PostgresConfig = {
15
17
  password: process.env.POSTGRES_PASSWORD || 'postgres',
16
18
  };
17
19
 
20
+ const connectionString = `postgresql://${TEST_CONFIG.user}:${TEST_CONFIG.password}@${TEST_CONFIG.host}:${TEST_CONFIG.port}/${TEST_CONFIG.database}`;
21
+
18
22
  // Sample test data factory functions
19
23
  const createSampleThread = () => ({
20
24
  id: `thread-${randomUUID()}`,
@@ -87,11 +91,17 @@ describe('PostgresStore', () => {
87
91
  });
88
92
 
89
93
  beforeEach(async () => {
90
- // Clear tables before each test
91
- await store.clearTable({ tableName: TABLE_WORKFLOW_SNAPSHOT });
92
- await store.clearTable({ tableName: TABLE_MESSAGES });
93
- await store.clearTable({ tableName: TABLE_THREADS });
94
- await store.clearTable({ tableName: TABLE_EVALS });
94
+ // Only clear tables if store is initialized
95
+ try {
96
+ // Clear tables before each test
97
+ await store.clearTable({ tableName: TABLE_WORKFLOW_SNAPSHOT });
98
+ await store.clearTable({ tableName: TABLE_MESSAGES });
99
+ await store.clearTable({ tableName: TABLE_THREADS });
100
+ await store.clearTable({ tableName: TABLE_EVALS });
101
+ } catch (error) {
102
+ // Ignore errors during table clearing
103
+ console.warn('Error clearing tables:', error);
104
+ }
95
105
  });
96
106
 
97
107
  describe('Thread Operations', () => {
@@ -192,9 +202,9 @@ describe('PostgresStore', () => {
192
202
  await store.__saveThread({ thread });
193
203
 
194
204
  const messages = [
195
- { ...createSampleMessage(thread.id), content: [{ type: 'text', text: 'First' }] },
196
- { ...createSampleMessage(thread.id), content: [{ type: 'text', text: 'Second' }] },
197
- { ...createSampleMessage(thread.id), content: [{ type: 'text', text: 'Third' }] },
205
+ { ...createSampleMessage(thread.id), content: [{ type: 'text', text: 'First' }] as MessageType['content'] },
206
+ { ...createSampleMessage(thread.id), content: [{ type: 'text', text: 'Second' }] as MessageType['content'] },
207
+ { ...createSampleMessage(thread.id), content: [{ type: 'text', text: 'Third' }] as MessageType['content'] },
198
208
  ];
199
209
 
200
210
  await store.__saveMessages({ messages });
@@ -204,7 +214,7 @@ describe('PostgresStore', () => {
204
214
 
205
215
  // Verify order is maintained
206
216
  retrievedMessages.forEach((msg, idx) => {
207
- expect(msg.content[0].text).toBe(messages[idx].content[0].text);
217
+ expect((msg.content[0] as any).text).toBe((messages[idx].content[0] as any).text);
208
218
  });
209
219
  });
210
220
 
@@ -214,7 +224,7 @@ describe('PostgresStore', () => {
214
224
 
215
225
  const messages = [
216
226
  createSampleMessage(thread.id),
217
- { ...createSampleMessage(thread.id), id: null }, // This will cause an error
227
+ { ...createSampleMessage(thread.id), id: null } as any, // This will cause an error
218
228
  ];
219
229
 
220
230
  await expect(store.__saveMessages({ messages })).rejects.toThrow();
@@ -645,7 +655,262 @@ describe('PostgresStore', () => {
645
655
  });
646
656
  });
647
657
 
658
+ describe('Schema Support', () => {
659
+ const customSchema = 'mastra_test';
660
+ let customSchemaStore: PostgresStore;
661
+
662
+ beforeAll(async () => {
663
+ customSchemaStore = new PostgresStore({
664
+ ...TEST_CONFIG,
665
+ schema: customSchema,
666
+ });
667
+
668
+ await customSchemaStore.init();
669
+ });
670
+
671
+ afterAll(async () => {
672
+ await customSchemaStore.close();
673
+ // Re-initialize the main store for subsequent tests
674
+ store = new PostgresStore(TEST_CONFIG);
675
+ await store.init();
676
+ });
677
+
678
+ describe('Constructor and Initialization', () => {
679
+ it('should accept connectionString directly', () => {
680
+ // Use existing store instead of creating new one
681
+ expect(store).toBeInstanceOf(PostgresStore);
682
+ });
683
+
684
+ it('should accept config object with schema', () => {
685
+ // Use existing custom schema store
686
+ expect(customSchemaStore).toBeInstanceOf(PostgresStore);
687
+ });
688
+ });
689
+
690
+ describe('Schema Operations', () => {
691
+ it('should create and query tables in custom schema', async () => {
692
+ // Create thread in custom schema
693
+ const thread = createSampleThread();
694
+ await customSchemaStore.__saveThread({ thread });
695
+
696
+ // Verify thread exists in custom schema
697
+ const retrieved = await customSchemaStore.__getThreadById({ threadId: thread.id });
698
+ expect(retrieved?.title).toBe(thread.title);
699
+ });
700
+
701
+ it('should allow same table names in different schemas', async () => {
702
+ // Create threads in both schemas
703
+ const defaultThread = createSampleThread();
704
+ const customThread = createSampleThread();
705
+
706
+ await store.__saveThread({ thread: defaultThread });
707
+ await customSchemaStore.__saveThread({ thread: customThread });
708
+
709
+ // Verify threads exist in respective schemas
710
+ const defaultResult = await store.__getThreadById({ threadId: defaultThread.id });
711
+ const customResult = await customSchemaStore.__getThreadById({ threadId: customThread.id });
712
+
713
+ expect(defaultResult?.id).toBe(defaultThread.id);
714
+ expect(customResult?.id).toBe(customThread.id);
715
+
716
+ // Verify cross-schema isolation
717
+ const defaultInCustom = await customSchemaStore.__getThreadById({ threadId: defaultThread.id });
718
+ const customInDefault = await store.__getThreadById({ threadId: customThread.id });
719
+
720
+ expect(defaultInCustom).toBeNull();
721
+ expect(customInDefault).toBeNull();
722
+ });
723
+ });
724
+ });
725
+
726
+ describe('Permission Handling', () => {
727
+ const schemaRestrictedUser = 'mastra_schema_restricted_storage';
728
+ const restrictedPassword = 'test123';
729
+ const testSchema = 'test_schema';
730
+ let adminDb: pgPromise.IDatabase<{}>;
731
+ let pgpAdmin: pgPromise.IMain;
732
+
733
+ beforeAll(async () => {
734
+ // Create a separate pg-promise instance for admin operations
735
+ pgpAdmin = pgPromise();
736
+ adminDb = pgpAdmin(connectionString);
737
+ try {
738
+ await adminDb.tx(async t => {
739
+ // Drop the test schema if it exists from previous runs
740
+ await t.none(`DROP SCHEMA IF EXISTS ${testSchema} CASCADE`);
741
+
742
+ // Create schema restricted user with minimal permissions
743
+ await t.none(`
744
+ DO $$
745
+ BEGIN
746
+ IF NOT EXISTS (SELECT FROM pg_catalog.pg_roles WHERE rolname = '${schemaRestrictedUser}') THEN
747
+ CREATE USER ${schemaRestrictedUser} WITH PASSWORD '${restrictedPassword}' NOCREATEDB;
748
+ END IF;
749
+ END
750
+ $$;`);
751
+
752
+ // Grant only connect and usage to schema restricted user
753
+ await t.none(`
754
+ REVOKE ALL ON DATABASE ${TEST_CONFIG.database} FROM ${schemaRestrictedUser};
755
+ GRANT CONNECT ON DATABASE ${TEST_CONFIG.database} TO ${schemaRestrictedUser};
756
+ REVOKE ALL ON SCHEMA public FROM ${schemaRestrictedUser};
757
+ GRANT USAGE ON SCHEMA public TO ${schemaRestrictedUser};
758
+ `);
759
+ });
760
+ } catch (error) {
761
+ // Clean up the database connection on error
762
+ pgpAdmin.end();
763
+ throw error;
764
+ }
765
+ });
766
+
767
+ afterAll(async () => {
768
+ try {
769
+ // First close any store connections
770
+ if (store) {
771
+ await store.close();
772
+ }
773
+
774
+ // Then clean up test user in admin connection
775
+ await adminDb.tx(async t => {
776
+ await t.none(`
777
+ REASSIGN OWNED BY ${schemaRestrictedUser} TO postgres;
778
+ DROP OWNED BY ${schemaRestrictedUser};
779
+ DROP USER IF EXISTS ${schemaRestrictedUser};
780
+ `);
781
+ });
782
+
783
+ // Finally clean up admin connection
784
+ if (pgpAdmin) {
785
+ pgpAdmin.end();
786
+ }
787
+ } catch (error) {
788
+ console.error('Error cleaning up test user:', error);
789
+ // Still try to clean up connections even if user cleanup fails
790
+ if (store) await store.close();
791
+ if (pgpAdmin) pgpAdmin.end();
792
+ }
793
+ });
794
+
795
+ describe('Schema Creation', () => {
796
+ beforeEach(async () => {
797
+ // Create a fresh connection for each test
798
+ const tempPgp = pgPromise();
799
+ const tempDb = tempPgp(connectionString);
800
+
801
+ try {
802
+ // Ensure schema doesn't exist before each test
803
+ await tempDb.none(`DROP SCHEMA IF EXISTS ${testSchema} CASCADE`);
804
+
805
+ // Ensure no active connections from restricted user
806
+ await tempDb.none(`
807
+ SELECT pg_terminate_backend(pid)
808
+ FROM pg_stat_activity
809
+ WHERE usename = '${schemaRestrictedUser}'
810
+ `);
811
+ } finally {
812
+ tempPgp.end(); // Always clean up the connection
813
+ }
814
+ });
815
+
816
+ afterEach(async () => {
817
+ // Create a fresh connection for cleanup
818
+ const tempPgp = pgPromise();
819
+ const tempDb = tempPgp(connectionString);
820
+
821
+ try {
822
+ // Clean up any connections from the restricted user and drop schema
823
+ await tempDb.none(`
824
+ DO $$
825
+ BEGIN
826
+ -- Terminate connections
827
+ PERFORM pg_terminate_backend(pid)
828
+ FROM pg_stat_activity
829
+ WHERE usename = '${schemaRestrictedUser}';
830
+
831
+ -- Drop schema
832
+ DROP SCHEMA IF EXISTS ${testSchema} CASCADE;
833
+ END $$;
834
+ `);
835
+ } catch (error) {
836
+ console.error('Error in afterEach cleanup:', error);
837
+ } finally {
838
+ tempPgp.end(); // Always clean up the connection
839
+ }
840
+ });
841
+
842
+ it('should fail when user lacks CREATE privilege', async () => {
843
+ const restrictedDB = new PostgresStore({
844
+ ...TEST_CONFIG,
845
+ user: schemaRestrictedUser,
846
+ password: restrictedPassword,
847
+ schema: testSchema,
848
+ });
849
+
850
+ // Create a fresh connection for verification
851
+ const tempPgp = pgPromise();
852
+ const tempDb = tempPgp(connectionString);
853
+
854
+ try {
855
+ // Test schema creation by initializing the store
856
+ await expect(async () => {
857
+ await restrictedDB.init();
858
+ }).rejects.toThrow(
859
+ `Unable to create schema "${testSchema}". This requires CREATE privilege on the database.`,
860
+ );
861
+
862
+ // Verify schema was not created
863
+ const exists = await tempDb.oneOrNone(
864
+ `SELECT EXISTS (SELECT 1 FROM information_schema.schemata WHERE schema_name = $1)`,
865
+ [testSchema],
866
+ );
867
+ expect(exists?.exists).toBe(false);
868
+ } finally {
869
+ await restrictedDB.close();
870
+ tempPgp.end(); // Clean up the verification connection
871
+ }
872
+ });
873
+
874
+ it('should fail with schema creation error when saving thread', async () => {
875
+ const restrictedDB = new PostgresStore({
876
+ ...TEST_CONFIG,
877
+ user: schemaRestrictedUser,
878
+ password: restrictedPassword,
879
+ schema: testSchema,
880
+ });
881
+
882
+ // Create a fresh connection for verification
883
+ const tempPgp = pgPromise();
884
+ const tempDb = tempPgp(connectionString);
885
+
886
+ try {
887
+ await expect(async () => {
888
+ await restrictedDB.init();
889
+ const thread = createSampleThread();
890
+ await restrictedDB.__saveThread({ thread });
891
+ }).rejects.toThrow(
892
+ `Unable to create schema "${testSchema}". This requires CREATE privilege on the database.`,
893
+ );
894
+
895
+ // Verify schema was not created
896
+ const exists = await tempDb.oneOrNone(
897
+ `SELECT EXISTS (SELECT 1 FROM information_schema.schemata WHERE schema_name = $1)`,
898
+ [testSchema],
899
+ );
900
+ expect(exists?.exists).toBe(false);
901
+ } finally {
902
+ await restrictedDB.close();
903
+ tempPgp.end(); // Clean up the verification connection
904
+ }
905
+ });
906
+ });
907
+ });
908
+
648
909
  afterAll(async () => {
649
- await store.close();
910
+ try {
911
+ await store.close();
912
+ } catch (error) {
913
+ console.warn('Error closing store:', error);
914
+ }
650
915
  });
651
916
  });
@@ -13,7 +13,7 @@ import type { WorkflowRunState } from '@mastra/core/workflows';
13
13
  import pgPromise from 'pg-promise';
14
14
  import type { ISSLConfig } from 'pg-promise/typescript/pg-subset';
15
15
 
16
- export type PostgresConfig =
16
+ export type PostgresConfig = { schema?: string } & (
17
17
  | {
18
18
  host: string;
19
19
  port: number;
@@ -24,15 +24,20 @@ export type PostgresConfig =
24
24
  }
25
25
  | {
26
26
  connectionString: string;
27
- };
27
+ }
28
+ );
28
29
 
29
30
  export class PostgresStore extends MastraStorage {
30
31
  private db: pgPromise.IDatabase<{}>;
31
32
  private pgp: pgPromise.IMain;
33
+ private schema?: string;
34
+ private setupSchemaPromise: Promise<void> | null = null;
35
+ private schemaSetupComplete: boolean | undefined = undefined;
32
36
 
33
37
  constructor(config: PostgresConfig) {
34
38
  super({ name: 'PostgresStore' });
35
39
  this.pgp = pgPromise();
40
+ this.schema = config.schema;
36
41
  this.db = this.pgp(
37
42
  `connectionString` in config
38
43
  ? { connectionString: config.connectionString }
@@ -47,9 +52,13 @@ export class PostgresStore extends MastraStorage {
47
52
  );
48
53
  }
49
54
 
55
+ private getTableName(indexName: string) {
56
+ return this.schema ? `${this.schema}."${indexName}"` : `"${indexName}"`;
57
+ }
58
+
50
59
  async getEvalsByAgentName(agentName: string, type?: 'test' | 'live'): Promise<EvalRow[]> {
51
60
  try {
52
- const baseQuery = `SELECT * FROM ${TABLE_EVALS} WHERE agent_name = $1`;
61
+ const baseQuery = `SELECT * FROM ${this.getTableName(TABLE_EVALS)} WHERE agent_name = $1`;
53
62
  const typeCondition =
54
63
  type === 'test'
55
64
  ? " AND test_info IS NOT NULL AND test_info->>'testPath' IS NOT NULL"
@@ -186,7 +195,10 @@ export class PostgresStore extends MastraStorage {
186
195
  endTime: string;
187
196
  other: any;
188
197
  createdAt: string;
189
- }>(`SELECT * FROM ${TABLE_TRACES} ${whereClause} ORDER BY "createdAt" DESC LIMIT ${limit} OFFSET ${offset}`, args);
198
+ }>(
199
+ `SELECT * FROM ${this.getTableName(TABLE_TRACES)} ${whereClause} ORDER BY "createdAt" DESC LIMIT ${limit} OFFSET ${offset}`,
200
+ args,
201
+ );
190
202
 
191
203
  if (!result) {
192
204
  return [];
@@ -210,6 +222,55 @@ export class PostgresStore extends MastraStorage {
210
222
  })) as any;
211
223
  }
212
224
 
225
+ private async setupSchema() {
226
+ if (!this.schema || this.schemaSetupComplete) {
227
+ return;
228
+ }
229
+
230
+ if (!this.setupSchemaPromise) {
231
+ this.setupSchemaPromise = (async () => {
232
+ try {
233
+ // First check if schema exists and we have usage permission
234
+ const schemaExists = await this.db.oneOrNone(
235
+ `
236
+ SELECT EXISTS (
237
+ SELECT 1 FROM information_schema.schemata
238
+ WHERE schema_name = $1
239
+ )
240
+ `,
241
+ [this.schema],
242
+ );
243
+
244
+ if (!schemaExists?.exists) {
245
+ try {
246
+ await this.db.none(`CREATE SCHEMA IF NOT EXISTS ${this.schema}`);
247
+ this.logger.info(`Schema "${this.schema}" created successfully`);
248
+ } catch (error) {
249
+ this.logger.error(`Failed to create schema "${this.schema}"`, { error });
250
+ throw new Error(
251
+ `Unable to create schema "${this.schema}". This requires CREATE privilege on the database. ` +
252
+ `Either create the schema manually or grant CREATE privilege to the user.`,
253
+ );
254
+ }
255
+ }
256
+
257
+ // If we got here, schema exists and we can use it
258
+ this.schemaSetupComplete = true;
259
+ this.logger.debug(`Schema "${this.schema}" is ready for use`);
260
+ } catch (error) {
261
+ // Reset flags so we can retry
262
+ this.schemaSetupComplete = undefined;
263
+ this.setupSchemaPromise = null;
264
+ throw error;
265
+ } finally {
266
+ this.setupSchemaPromise = null;
267
+ }
268
+ })();
269
+ }
270
+
271
+ await this.setupSchemaPromise;
272
+ }
273
+
213
274
  async createTable({
214
275
  tableName,
215
276
  schema,
@@ -227,8 +288,13 @@ export class PostgresStore extends MastraStorage {
227
288
  })
228
289
  .join(',\n');
229
290
 
291
+ // Create schema if it doesn't exist
292
+ if (this.schema) {
293
+ await this.setupSchema();
294
+ }
295
+
230
296
  const sql = `
231
- CREATE TABLE IF NOT EXISTS ${tableName} (
297
+ CREATE TABLE IF NOT EXISTS ${this.getTableName(tableName)} (
232
298
  ${columns}
233
299
  );
234
300
  ${
@@ -238,7 +304,7 @@ export class PostgresStore extends MastraStorage {
238
304
  IF NOT EXISTS (
239
305
  SELECT 1 FROM pg_constraint WHERE conname = 'mastra_workflow_snapshot_workflow_name_run_id_key'
240
306
  ) THEN
241
- ALTER TABLE ${tableName}
307
+ ALTER TABLE ${this.getTableName(tableName)}
242
308
  ADD CONSTRAINT mastra_workflow_snapshot_workflow_name_run_id_key
243
309
  UNIQUE (workflow_name, run_id);
244
310
  END IF;
@@ -257,7 +323,7 @@ export class PostgresStore extends MastraStorage {
257
323
 
258
324
  async clearTable({ tableName }: { tableName: TABLE_NAMES }): Promise<void> {
259
325
  try {
260
- await this.db.none(`TRUNCATE TABLE ${tableName} CASCADE`);
326
+ await this.db.none(`TRUNCATE TABLE ${this.getTableName(tableName)} CASCADE`);
261
327
  } catch (error) {
262
328
  console.error(`Error clearing table ${tableName}:`, error);
263
329
  throw error;
@@ -271,7 +337,7 @@ export class PostgresStore extends MastraStorage {
271
337
  const placeholders = values.map((_, i) => `$${i + 1}`).join(', ');
272
338
 
273
339
  await this.db.none(
274
- `INSERT INTO ${tableName} (${columns.map(c => `"${c}"`).join(', ')}) VALUES (${placeholders})`,
340
+ `INSERT INTO ${this.getTableName(tableName)} (${columns.map(c => `"${c}"`).join(', ')}) VALUES (${placeholders})`,
275
341
  values,
276
342
  );
277
343
  } catch (error) {
@@ -286,7 +352,10 @@ export class PostgresStore extends MastraStorage {
286
352
  const conditions = keyEntries.map(([key], index) => `"${key}" = $${index + 1}`).join(' AND ');
287
353
  const values = keyEntries.map(([_, value]) => value);
288
354
 
289
- const result = await this.db.oneOrNone<R>(`SELECT * FROM ${tableName} WHERE ${conditions}`, values);
355
+ const result = await this.db.oneOrNone<R>(
356
+ `SELECT * FROM ${this.getTableName(tableName)} WHERE ${conditions}`,
357
+ values,
358
+ );
290
359
 
291
360
  if (!result) {
292
361
  return null;
@@ -318,7 +387,7 @@ export class PostgresStore extends MastraStorage {
318
387
  metadata,
319
388
  "createdAt",
320
389
  "updatedAt"
321
- FROM "${TABLE_THREADS}"
390
+ FROM ${this.getTableName(TABLE_THREADS)}
322
391
  WHERE id = $1`,
323
392
  [threadId],
324
393
  );
@@ -349,7 +418,7 @@ export class PostgresStore extends MastraStorage {
349
418
  metadata,
350
419
  "createdAt",
351
420
  "updatedAt"
352
- FROM "${TABLE_THREADS}"
421
+ FROM ${this.getTableName(TABLE_THREADS)}
353
422
  WHERE "resourceId" = $1`,
354
423
  [resourceId],
355
424
  );
@@ -369,7 +438,7 @@ export class PostgresStore extends MastraStorage {
369
438
  async saveThread({ thread }: { thread: StorageThreadType }): Promise<StorageThreadType> {
370
439
  try {
371
440
  await this.db.none(
372
- `INSERT INTO "${TABLE_THREADS}" (
441
+ `INSERT INTO ${this.getTableName(TABLE_THREADS)} (
373
442
  id,
374
443
  "resourceId",
375
444
  title,
@@ -423,7 +492,7 @@ export class PostgresStore extends MastraStorage {
423
492
  };
424
493
 
425
494
  const thread = await this.db.one<StorageThreadType>(
426
- `UPDATE "${TABLE_THREADS}"
495
+ `UPDATE ${this.getTableName(TABLE_THREADS)}
427
496
  SET title = $1,
428
497
  metadata = $2,
429
498
  "updatedAt" = $3
@@ -448,10 +517,10 @@ export class PostgresStore extends MastraStorage {
448
517
  try {
449
518
  await this.db.tx(async t => {
450
519
  // First delete all messages associated with this thread
451
- await t.none(`DELETE FROM "${TABLE_MESSAGES}" WHERE thread_id = $1`, [threadId]);
520
+ await t.none(`DELETE FROM ${this.getTableName(TABLE_MESSAGES)} WHERE thread_id = $1`, [threadId]);
452
521
 
453
522
  // Then delete the thread
454
- await t.none(`DELETE FROM "${TABLE_THREADS}" WHERE id = $1`, [threadId]);
523
+ await t.none(`DELETE FROM ${this.getTableName(TABLE_THREADS)} WHERE id = $1`, [threadId]);
455
524
  });
456
525
  } catch (error) {
457
526
  console.error('Error deleting thread:', error);
@@ -472,7 +541,7 @@ export class PostgresStore extends MastraStorage {
472
541
  SELECT
473
542
  *,
474
543
  ROW_NUMBER() OVER (ORDER BY "createdAt" DESC) as row_num
475
- FROM "${TABLE_MESSAGES}"
544
+ FROM ${this.getTableName(TABLE_MESSAGES)}
476
545
  WHERE thread_id = $1
477
546
  )
478
547
  SELECT
@@ -518,7 +587,7 @@ export class PostgresStore extends MastraStorage {
518
587
  type,
519
588
  "createdAt",
520
589
  thread_id AS "threadId"
521
- FROM "${TABLE_MESSAGES}"
590
+ FROM ${this.getTableName(TABLE_MESSAGES)}
522
591
  WHERE thread_id = $1
523
592
  AND id != ALL($2)
524
593
  ORDER BY "createdAt" DESC
@@ -568,7 +637,7 @@ export class PostgresStore extends MastraStorage {
568
637
  await this.db.tx(async t => {
569
638
  for (const message of messages) {
570
639
  await t.none(
571
- `INSERT INTO "${TABLE_MESSAGES}" (id, thread_id, content, "createdAt", role, type)
640
+ `INSERT INTO ${this.getTableName(TABLE_MESSAGES)} (id, thread_id, content, "createdAt", role, type)
572
641
  VALUES ($1, $2, $3, $4, $5, $6)`,
573
642
  [
574
643
  message.id,
@@ -601,7 +670,7 @@ export class PostgresStore extends MastraStorage {
601
670
  try {
602
671
  const now = new Date().toISOString();
603
672
  await this.db.none(
604
- `INSERT INTO "${TABLE_WORKFLOW_SNAPSHOT}" (
673
+ `INSERT INTO ${this.getTableName(TABLE_WORKFLOW_SNAPSHOT)} (
605
674
  workflow_name,
606
675
  run_id,
607
676
  snapshot,
@@ -696,7 +765,7 @@ export class PostgresStore extends MastraStorage {
696
765
  // Only get total count when using pagination
697
766
  if (limit !== undefined && offset !== undefined) {
698
767
  const countResult = await this.db.one(
699
- `SELECT COUNT(*) as count FROM ${TABLE_WORKFLOW_SNAPSHOT} ${whereClause}`,
768
+ `SELECT COUNT(*) as count FROM ${this.getTableName(TABLE_WORKFLOW_SNAPSHOT)} ${whereClause}`,
700
769
  values,
701
770
  );
702
771
  total = Number(countResult.count);
@@ -704,7 +773,7 @@ export class PostgresStore extends MastraStorage {
704
773
 
705
774
  // Get results
706
775
  const query = `
707
- SELECT * FROM ${TABLE_WORKFLOW_SNAPSHOT}
776
+ SELECT * FROM ${this.getTableName(TABLE_WORKFLOW_SNAPSHOT)}
708
777
  ${whereClause}
709
778
  ORDER BY "createdAt" DESC
710
779
  ${limit !== undefined && offset !== undefined ? ` LIMIT $${paramIndex} OFFSET $${paramIndex + 1}` : ''}