@mastra/pg 0.11.0-alpha.1 → 0.11.0-alpha.3

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,23 +1,23 @@
1
1
 
2
- > @mastra/pg@0.11.0-alpha.1 build /home/runner/work/mastra/mastra/stores/pg
2
+ > @mastra/pg@0.11.0-alpha.3 build /home/runner/work/mastra/mastra/stores/pg
3
3
  > tsup src/index.ts --format esm,cjs --experimental-dts --clean --treeshake=smallest --splitting
4
4
 
5
5
  CLI Building entry: src/index.ts
6
6
  CLI Using tsconfig: tsconfig.json
7
7
  CLI tsup v8.5.0
8
8
  TSC Build start
9
- TSC ⚡️ Build success in 10371ms
9
+ TSC ⚡️ Build success in 10074ms
10
10
  DTS Build start
11
11
  CLI Target: es2022
12
12
  Analysis will use the bundled TypeScript version 5.8.3
13
13
  Writing package typings: /home/runner/work/mastra/mastra/stores/pg/dist/_tsup-dts-rollup.d.ts
14
14
  Analysis will use the bundled TypeScript version 5.8.3
15
15
  Writing package typings: /home/runner/work/mastra/mastra/stores/pg/dist/_tsup-dts-rollup.d.cts
16
- DTS ⚡️ Build success in 11657ms
16
+ DTS ⚡️ Build success in 11524ms
17
17
  CLI Cleaning output folder
18
18
  ESM Build start
19
19
  CJS Build start
20
- CJS dist/index.cjs 68.06 KB
21
- CJS ⚡️ Build success in 1500ms
22
- ESM dist/index.js 67.49 KB
23
- ESM ⚡️ Build success in 1504ms
20
+ CJS dist/index.cjs 68.48 KB
21
+ CJS ⚡️ Build success in 1389ms
22
+ ESM dist/index.js 67.91 KB
23
+ ESM ⚡️ Build success in 1390ms
package/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  # @mastra/pg
2
2
 
3
+ ## 0.11.0-alpha.3
4
+
5
+ ### Patch Changes
6
+
7
+ - 6c23252: [MASTRA-3982] Fix Memory Retrieval for PG when scope is resource
8
+ - Updated dependencies [9589624]
9
+ - @mastra/core@0.10.6-alpha.4
10
+
11
+ ## 0.11.0-alpha.2
12
+
13
+ ### Patch Changes
14
+
15
+ - eed55d7: quotes table and schema names for vector and storage to allow for camelcase
16
+ - Updated dependencies [d70c420]
17
+ - Updated dependencies [2a16996]
18
+ - @mastra/core@0.10.6-alpha.3
19
+
3
20
  ## 0.11.0-alpha.1
4
21
 
5
22
  ### Minor Changes
@@ -196,6 +196,7 @@ declare class PgVector extends MastraVector {
196
196
  });
197
197
  private getMutexByName;
198
198
  private getTableName;
199
+ private getSchemaName;
199
200
  transformFilter(filter?: VectorFilter): VectorFilter;
200
201
  getIndexInfo({ indexName }: DescribeIndexParams): Promise<PGIndexStats>;
201
202
  query({ indexName, queryVector, topK, filter, includeVector, minScore, ef, probes, }: PgQueryVectorParams): Promise<QueryResult[]>;
@@ -276,6 +277,7 @@ declare class PostgresStore extends MastraStorage {
276
277
  selectByIncludeResourceScope: boolean;
277
278
  };
278
279
  private getTableName;
280
+ private getSchemaName;
279
281
  /** @deprecated use getEvals instead */
280
282
  getEvalsByAgentName(agentName: string, type?: 'test' | 'live'): Promise<EvalRow[]>;
281
283
  private transformEvalRow;
@@ -196,6 +196,7 @@ declare class PgVector extends MastraVector {
196
196
  });
197
197
  private getMutexByName;
198
198
  private getTableName;
199
+ private getSchemaName;
199
200
  transformFilter(filter?: VectorFilter): VectorFilter;
200
201
  getIndexInfo({ indexName }: DescribeIndexParams): Promise<PGIndexStats>;
201
202
  query({ indexName, queryVector, topK, filter, includeVector, minScore, ef, probes, }: PgQueryVectorParams): Promise<QueryResult[]>;
@@ -276,6 +277,7 @@ declare class PostgresStore extends MastraStorage {
276
277
  selectByIncludeResourceScope: boolean;
277
278
  };
278
279
  private getTableName;
280
+ private getSchemaName;
279
281
  /** @deprecated use getEvals instead */
280
282
  getEvalsByAgentName(agentName: string, type?: 'test' | 'live'): Promise<EvalRow[]>;
281
283
  private transformEvalRow;
package/dist/index.cjs CHANGED
@@ -420,8 +420,16 @@ var PgVector = class extends vector.MastraVector {
420
420
  }
421
421
  getTableName(indexName) {
422
422
  const parsedIndexName = utils.parseSqlIdentifier(indexName, "index name");
423
- const parsedSchemaName = this.schema ? utils.parseSqlIdentifier(this.schema, "schema name") : void 0;
424
- return parsedSchemaName ? `${parsedSchemaName}.${parsedIndexName}` : parsedIndexName;
423
+ const quotedIndexName = `"${parsedIndexName}"`;
424
+ const quotedSchemaName = this.getSchemaName();
425
+ const quotedVectorName = `"${parsedIndexName}_vector_idx"`;
426
+ return {
427
+ tableName: quotedSchemaName ? `${quotedSchemaName}.${quotedIndexName}` : quotedIndexName,
428
+ vectorIndexName: quotedVectorName
429
+ };
430
+ }
431
+ getSchemaName() {
432
+ return this.schema ? `"${utils.parseSqlIdentifier(this.schema, "schema name")}"` : void 0;
425
433
  }
426
434
  transformFilter(filter) {
427
435
  const translator = new PGFilterTranslator();
@@ -463,7 +471,7 @@ var PgVector = class extends vector.MastraVector {
463
471
  if (indexInfo.type === "ivfflat" && probes) {
464
472
  await client.query(`SET LOCAL ivfflat.probes = ${probes}`);
465
473
  }
466
- const tableName = this.getTableName(indexName);
474
+ const { tableName } = this.getTableName(indexName);
467
475
  const query = `
468
476
  WITH vector_scores AS (
469
477
  SELECT
@@ -491,7 +499,7 @@ var PgVector = class extends vector.MastraVector {
491
499
  }
492
500
  }
493
501
  async upsert({ indexName, vectors, metadata, ids }) {
494
- const tableName = this.getTableName(indexName);
502
+ const { tableName } = this.getTableName(indexName);
495
503
  const client = await this.pool.connect();
496
504
  try {
497
505
  await client.query("BEGIN");
@@ -559,7 +567,7 @@ var PgVector = class extends vector.MastraVector {
559
567
  const schemaExists = schemaCheck.rows[0].exists;
560
568
  if (!schemaExists) {
561
569
  try {
562
- await client.query(`CREATE SCHEMA IF NOT EXISTS ${this.schema}`);
570
+ await client.query(`CREATE SCHEMA IF NOT EXISTS ${this.getSchemaName()}`);
563
571
  this.logger.info(`Schema "${this.schema}" created successfully`);
564
572
  } catch (error) {
565
573
  this.logger.error(`Failed to create schema "${this.schema}"`, { error });
@@ -588,7 +596,7 @@ var PgVector = class extends vector.MastraVector {
588
596
  indexConfig = {},
589
597
  buildIndex = true
590
598
  }) {
591
- const tableName = this.getTableName(indexName);
599
+ const { tableName } = this.getTableName(indexName);
592
600
  if (!indexName.match(/^[a-zA-Z_][a-zA-Z0-9_]*$/)) {
593
601
  throw new Error("Invalid index name format");
594
602
  }
@@ -639,9 +647,9 @@ var PgVector = class extends vector.MastraVector {
639
647
  async setupIndex({ indexName, metric, indexConfig }, client) {
640
648
  const mutex = this.getMutexByName(`build-${indexName}`);
641
649
  await mutex.runExclusive(async () => {
642
- const tableName = this.getTableName(indexName);
650
+ const { tableName, vectorIndexName } = this.getTableName(indexName);
643
651
  if (this.createdIndexes.has(indexName)) {
644
- await client.query(`DROP INDEX IF EXISTS ${tableName}_vector_idx`);
652
+ await client.query(`DROP INDEX IF EXISTS ${vectorIndexName}`);
645
653
  }
646
654
  if (indexConfig.type === "flat") {
647
655
  this.describeIndexCache.delete(indexName);
@@ -653,7 +661,7 @@ var PgVector = class extends vector.MastraVector {
653
661
  const m = indexConfig.hnsw?.m ?? 8;
654
662
  const efConstruction = indexConfig.hnsw?.efConstruction ?? 32;
655
663
  indexSQL = `
656
- CREATE INDEX IF NOT EXISTS ${indexName}_vector_idx
664
+ CREATE INDEX IF NOT EXISTS ${vectorIndexName}
657
665
  ON ${tableName}
658
666
  USING hnsw (embedding ${metricOp})
659
667
  WITH (
@@ -670,7 +678,7 @@ var PgVector = class extends vector.MastraVector {
670
678
  lists = Math.max(100, Math.min(4e3, Math.floor(Math.sqrt(size) * 2)));
671
679
  }
672
680
  indexSQL = `
673
- CREATE INDEX IF NOT EXISTS ${indexName}_vector_idx
681
+ CREATE INDEX IF NOT EXISTS ${vectorIndexName}
674
682
  ON ${tableName}
675
683
  USING ivfflat (embedding ${metricOp})
676
684
  WITH (lists = ${lists});
@@ -741,7 +749,7 @@ var PgVector = class extends vector.MastraVector {
741
749
  async describeIndex({ indexName }) {
742
750
  const client = await this.pool.connect();
743
751
  try {
744
- const tableName = this.getTableName(indexName);
752
+ const { tableName } = this.getTableName(indexName);
745
753
  const tableExistsQuery = `
746
754
  SELECT 1
747
755
  FROM information_schema.columns
@@ -815,7 +823,7 @@ var PgVector = class extends vector.MastraVector {
815
823
  async deleteIndex({ indexName }) {
816
824
  const client = await this.pool.connect();
817
825
  try {
818
- const tableName = this.getTableName(indexName);
826
+ const { tableName } = this.getTableName(indexName);
819
827
  await client.query(`DROP TABLE IF EXISTS ${tableName} CASCADE`);
820
828
  this.createdIndexes.delete(indexName);
821
829
  } catch (error) {
@@ -828,7 +836,7 @@ var PgVector = class extends vector.MastraVector {
828
836
  async truncateIndex({ indexName }) {
829
837
  const client = await this.pool.connect();
830
838
  try {
831
- const tableName = this.getTableName(indexName);
839
+ const { tableName } = this.getTableName(indexName);
832
840
  await client.query(`TRUNCATE ${tableName}`);
833
841
  } catch (e) {
834
842
  await client.query("ROLLBACK");
@@ -871,7 +879,7 @@ var PgVector = class extends vector.MastraVector {
871
879
  if (updateParts.length === 0) {
872
880
  return;
873
881
  }
874
- const tableName = this.getTableName(indexName);
882
+ const { tableName } = this.getTableName(indexName);
875
883
  const query = `
876
884
  UPDATE ${tableName}
877
885
  SET ${updateParts.join(", ")}
@@ -894,7 +902,7 @@ var PgVector = class extends vector.MastraVector {
894
902
  async deleteVector({ indexName, id }) {
895
903
  const client = await this.pool.connect();
896
904
  try {
897
- const tableName = this.getTableName(indexName);
905
+ const { tableName } = this.getTableName(indexName);
898
906
  const query = `
899
907
  DELETE FROM ${tableName}
900
908
  WHERE vector_id = $1
@@ -950,9 +958,13 @@ var PostgresStore = class extends storage.MastraStorage {
950
958
  };
951
959
  }
952
960
  getTableName(indexName) {
953
- const parsedIndexName = utils.parseSqlIdentifier(indexName, "table name");
954
- const parsedSchemaName = this.schema ? utils.parseSqlIdentifier(this.schema, "schema name") : void 0;
955
- return parsedSchemaName ? `${parsedSchemaName}."${parsedIndexName}"` : `"${parsedIndexName}"`;
961
+ const parsedIndexName = utils.parseSqlIdentifier(indexName, "index name");
962
+ const quotedIndexName = `"${parsedIndexName}"`;
963
+ const quotedSchemaName = this.getSchemaName();
964
+ return quotedSchemaName ? `${quotedSchemaName}.${quotedIndexName}` : quotedIndexName;
965
+ }
966
+ getSchemaName() {
967
+ return this.schema ? `"${utils.parseSqlIdentifier(this.schema, "schema name")}"` : void 0;
956
968
  }
957
969
  /** @deprecated use getEvals instead */
958
970
  async getEvalsByAgentName(agentName, type) {
@@ -1117,7 +1129,7 @@ var PostgresStore = class extends storage.MastraStorage {
1117
1129
  );
1118
1130
  if (!schemaExists?.exists) {
1119
1131
  try {
1120
- await this.db.none(`CREATE SCHEMA IF NOT EXISTS ${this.schema}`);
1132
+ await this.db.none(`CREATE SCHEMA IF NOT EXISTS ${this.getSchemaName()}`);
1121
1133
  this.logger.info(`Schema "${this.schema}" created successfully`);
1122
1134
  } catch (error) {
1123
1135
  this.logger.error(`Failed to create schema "${this.schema}"`, { error });
@@ -1476,7 +1488,7 @@ var PostgresStore = class extends storage.MastraStorage {
1476
1488
  (m.row_num >= target.row_num - $${paramIdx + 3} AND m.row_num < target.row_num)
1477
1489
  )
1478
1490
  )
1479
- )
1491
+ ) AS query_${paramIdx}
1480
1492
  `
1481
1493
  // Keep ASC for final sorting after fetching context
1482
1494
  );
package/dist/index.js CHANGED
@@ -412,8 +412,16 @@ var PgVector = class extends MastraVector {
412
412
  }
413
413
  getTableName(indexName) {
414
414
  const parsedIndexName = parseSqlIdentifier(indexName, "index name");
415
- const parsedSchemaName = this.schema ? parseSqlIdentifier(this.schema, "schema name") : void 0;
416
- return parsedSchemaName ? `${parsedSchemaName}.${parsedIndexName}` : parsedIndexName;
415
+ const quotedIndexName = `"${parsedIndexName}"`;
416
+ const quotedSchemaName = this.getSchemaName();
417
+ const quotedVectorName = `"${parsedIndexName}_vector_idx"`;
418
+ return {
419
+ tableName: quotedSchemaName ? `${quotedSchemaName}.${quotedIndexName}` : quotedIndexName,
420
+ vectorIndexName: quotedVectorName
421
+ };
422
+ }
423
+ getSchemaName() {
424
+ return this.schema ? `"${parseSqlIdentifier(this.schema, "schema name")}"` : void 0;
417
425
  }
418
426
  transformFilter(filter) {
419
427
  const translator = new PGFilterTranslator();
@@ -455,7 +463,7 @@ var PgVector = class extends MastraVector {
455
463
  if (indexInfo.type === "ivfflat" && probes) {
456
464
  await client.query(`SET LOCAL ivfflat.probes = ${probes}`);
457
465
  }
458
- const tableName = this.getTableName(indexName);
466
+ const { tableName } = this.getTableName(indexName);
459
467
  const query = `
460
468
  WITH vector_scores AS (
461
469
  SELECT
@@ -483,7 +491,7 @@ var PgVector = class extends MastraVector {
483
491
  }
484
492
  }
485
493
  async upsert({ indexName, vectors, metadata, ids }) {
486
- const tableName = this.getTableName(indexName);
494
+ const { tableName } = this.getTableName(indexName);
487
495
  const client = await this.pool.connect();
488
496
  try {
489
497
  await client.query("BEGIN");
@@ -551,7 +559,7 @@ var PgVector = class extends MastraVector {
551
559
  const schemaExists = schemaCheck.rows[0].exists;
552
560
  if (!schemaExists) {
553
561
  try {
554
- await client.query(`CREATE SCHEMA IF NOT EXISTS ${this.schema}`);
562
+ await client.query(`CREATE SCHEMA IF NOT EXISTS ${this.getSchemaName()}`);
555
563
  this.logger.info(`Schema "${this.schema}" created successfully`);
556
564
  } catch (error) {
557
565
  this.logger.error(`Failed to create schema "${this.schema}"`, { error });
@@ -580,7 +588,7 @@ var PgVector = class extends MastraVector {
580
588
  indexConfig = {},
581
589
  buildIndex = true
582
590
  }) {
583
- const tableName = this.getTableName(indexName);
591
+ const { tableName } = this.getTableName(indexName);
584
592
  if (!indexName.match(/^[a-zA-Z_][a-zA-Z0-9_]*$/)) {
585
593
  throw new Error("Invalid index name format");
586
594
  }
@@ -631,9 +639,9 @@ var PgVector = class extends MastraVector {
631
639
  async setupIndex({ indexName, metric, indexConfig }, client) {
632
640
  const mutex = this.getMutexByName(`build-${indexName}`);
633
641
  await mutex.runExclusive(async () => {
634
- const tableName = this.getTableName(indexName);
642
+ const { tableName, vectorIndexName } = this.getTableName(indexName);
635
643
  if (this.createdIndexes.has(indexName)) {
636
- await client.query(`DROP INDEX IF EXISTS ${tableName}_vector_idx`);
644
+ await client.query(`DROP INDEX IF EXISTS ${vectorIndexName}`);
637
645
  }
638
646
  if (indexConfig.type === "flat") {
639
647
  this.describeIndexCache.delete(indexName);
@@ -645,7 +653,7 @@ var PgVector = class extends MastraVector {
645
653
  const m = indexConfig.hnsw?.m ?? 8;
646
654
  const efConstruction = indexConfig.hnsw?.efConstruction ?? 32;
647
655
  indexSQL = `
648
- CREATE INDEX IF NOT EXISTS ${indexName}_vector_idx
656
+ CREATE INDEX IF NOT EXISTS ${vectorIndexName}
649
657
  ON ${tableName}
650
658
  USING hnsw (embedding ${metricOp})
651
659
  WITH (
@@ -662,7 +670,7 @@ var PgVector = class extends MastraVector {
662
670
  lists = Math.max(100, Math.min(4e3, Math.floor(Math.sqrt(size) * 2)));
663
671
  }
664
672
  indexSQL = `
665
- CREATE INDEX IF NOT EXISTS ${indexName}_vector_idx
673
+ CREATE INDEX IF NOT EXISTS ${vectorIndexName}
666
674
  ON ${tableName}
667
675
  USING ivfflat (embedding ${metricOp})
668
676
  WITH (lists = ${lists});
@@ -733,7 +741,7 @@ var PgVector = class extends MastraVector {
733
741
  async describeIndex({ indexName }) {
734
742
  const client = await this.pool.connect();
735
743
  try {
736
- const tableName = this.getTableName(indexName);
744
+ const { tableName } = this.getTableName(indexName);
737
745
  const tableExistsQuery = `
738
746
  SELECT 1
739
747
  FROM information_schema.columns
@@ -807,7 +815,7 @@ var PgVector = class extends MastraVector {
807
815
  async deleteIndex({ indexName }) {
808
816
  const client = await this.pool.connect();
809
817
  try {
810
- const tableName = this.getTableName(indexName);
818
+ const { tableName } = this.getTableName(indexName);
811
819
  await client.query(`DROP TABLE IF EXISTS ${tableName} CASCADE`);
812
820
  this.createdIndexes.delete(indexName);
813
821
  } catch (error) {
@@ -820,7 +828,7 @@ var PgVector = class extends MastraVector {
820
828
  async truncateIndex({ indexName }) {
821
829
  const client = await this.pool.connect();
822
830
  try {
823
- const tableName = this.getTableName(indexName);
831
+ const { tableName } = this.getTableName(indexName);
824
832
  await client.query(`TRUNCATE ${tableName}`);
825
833
  } catch (e) {
826
834
  await client.query("ROLLBACK");
@@ -863,7 +871,7 @@ var PgVector = class extends MastraVector {
863
871
  if (updateParts.length === 0) {
864
872
  return;
865
873
  }
866
- const tableName = this.getTableName(indexName);
874
+ const { tableName } = this.getTableName(indexName);
867
875
  const query = `
868
876
  UPDATE ${tableName}
869
877
  SET ${updateParts.join(", ")}
@@ -886,7 +894,7 @@ var PgVector = class extends MastraVector {
886
894
  async deleteVector({ indexName, id }) {
887
895
  const client = await this.pool.connect();
888
896
  try {
889
- const tableName = this.getTableName(indexName);
897
+ const { tableName } = this.getTableName(indexName);
890
898
  const query = `
891
899
  DELETE FROM ${tableName}
892
900
  WHERE vector_id = $1
@@ -942,9 +950,13 @@ var PostgresStore = class extends MastraStorage {
942
950
  };
943
951
  }
944
952
  getTableName(indexName) {
945
- const parsedIndexName = parseSqlIdentifier(indexName, "table name");
946
- const parsedSchemaName = this.schema ? parseSqlIdentifier(this.schema, "schema name") : void 0;
947
- return parsedSchemaName ? `${parsedSchemaName}."${parsedIndexName}"` : `"${parsedIndexName}"`;
953
+ const parsedIndexName = parseSqlIdentifier(indexName, "index name");
954
+ const quotedIndexName = `"${parsedIndexName}"`;
955
+ const quotedSchemaName = this.getSchemaName();
956
+ return quotedSchemaName ? `${quotedSchemaName}.${quotedIndexName}` : quotedIndexName;
957
+ }
958
+ getSchemaName() {
959
+ return this.schema ? `"${parseSqlIdentifier(this.schema, "schema name")}"` : void 0;
948
960
  }
949
961
  /** @deprecated use getEvals instead */
950
962
  async getEvalsByAgentName(agentName, type) {
@@ -1109,7 +1121,7 @@ var PostgresStore = class extends MastraStorage {
1109
1121
  );
1110
1122
  if (!schemaExists?.exists) {
1111
1123
  try {
1112
- await this.db.none(`CREATE SCHEMA IF NOT EXISTS ${this.schema}`);
1124
+ await this.db.none(`CREATE SCHEMA IF NOT EXISTS ${this.getSchemaName()}`);
1113
1125
  this.logger.info(`Schema "${this.schema}" created successfully`);
1114
1126
  } catch (error) {
1115
1127
  this.logger.error(`Failed to create schema "${this.schema}"`, { error });
@@ -1468,7 +1480,7 @@ var PostgresStore = class extends MastraStorage {
1468
1480
  (m.row_num >= target.row_num - $${paramIdx + 3} AND m.row_num < target.row_num)
1469
1481
  )
1470
1482
  )
1471
- )
1483
+ ) AS query_${paramIdx}
1472
1484
  `
1473
1485
  // Keep ASC for final sorting after fetching context
1474
1486
  );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mastra/pg",
3
- "version": "0.11.0-alpha.1",
3
+ "version": "0.11.0-alpha.3",
4
4
  "description": "Postgres provider for Mastra - includes both vector and db storage capabilities",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -34,8 +34,8 @@
34
34
  "typescript": "^5.8.3",
35
35
  "vitest": "^3.2.3",
36
36
  "@internal/lint": "0.0.12",
37
- "@internal/storage-test-utils": "0.0.8",
38
- "@mastra/core": "0.10.6-alpha.0"
37
+ "@mastra/core": "0.10.6-alpha.4",
38
+ "@internal/storage-test-utils": "0.0.8"
39
39
  },
40
40
  "peerDependencies": {
41
41
  "@mastra/core": ">=0.10.4-0 <0.11.0"
@@ -1016,7 +1016,7 @@ describe('PostgresStore', () => {
1016
1016
  });
1017
1017
 
1018
1018
  describe('Schema Support', () => {
1019
- const customSchema = 'mastra_test';
1019
+ const customSchema = 'mastraTest';
1020
1020
  let customSchemaStore: PostgresStore;
1021
1021
 
1022
1022
  beforeAll(async () => {
@@ -1494,10 +1494,83 @@ describe('PostgresStore', () => {
1494
1494
  });
1495
1495
  });
1496
1496
 
1497
+ describe('PgStorage Table Name Quoting', () => {
1498
+ const camelCaseTable = 'TestCamelCaseTable';
1499
+ const snakeCaseTable = 'test_snake_case_table';
1500
+ const BASE_SCHEMA = {
1501
+ id: { type: 'integer', primaryKey: true, nullable: false },
1502
+ name: { type: 'text', nullable: true },
1503
+ } as Record<string, StorageColumn>;
1504
+
1505
+ beforeEach(async () => {
1506
+ // Only clear tables if store is initialized
1507
+ try {
1508
+ // Clear tables before each test
1509
+ await store.clearTable({ tableName: camelCaseTable as TABLE_NAMES });
1510
+ await store.clearTable({ tableName: snakeCaseTable as TABLE_NAMES });
1511
+ } catch (error) {
1512
+ // Ignore errors during table clearing
1513
+ console.warn('Error clearing tables:', error);
1514
+ }
1515
+ });
1516
+
1517
+ afterEach(async () => {
1518
+ // Only clear tables if store is initialized
1519
+ try {
1520
+ // Clear tables before each test
1521
+ await store.clearTable({ tableName: camelCaseTable as TABLE_NAMES });
1522
+ await store.clearTable({ tableName: snakeCaseTable as TABLE_NAMES });
1523
+ } catch (error) {
1524
+ // Ignore errors during table clearing
1525
+ console.warn('Error clearing tables:', error);
1526
+ }
1527
+ });
1528
+
1529
+ it('should create and upsert to a camelCase table without quoting errors', async () => {
1530
+ await expect(
1531
+ store.createTable({
1532
+ tableName: camelCaseTable as TABLE_NAMES,
1533
+ schema: BASE_SCHEMA,
1534
+ }),
1535
+ ).resolves.not.toThrow();
1536
+
1537
+ await store.insert({
1538
+ tableName: camelCaseTable as TABLE_NAMES,
1539
+ record: { id: '1', name: 'Alice' },
1540
+ });
1541
+
1542
+ const row = await store.load({
1543
+ tableName: camelCaseTable as TABLE_NAMES,
1544
+ keys: { id: '1' },
1545
+ });
1546
+ expect(row?.name).toBe('Alice');
1547
+ });
1548
+
1549
+ it('should create and upsert to a snake_case table without quoting errors', async () => {
1550
+ await expect(
1551
+ store.createTable({
1552
+ tableName: snakeCaseTable as TABLE_NAMES,
1553
+ schema: BASE_SCHEMA,
1554
+ }),
1555
+ ).resolves.not.toThrow();
1556
+
1557
+ await store.insert({
1558
+ tableName: snakeCaseTable as TABLE_NAMES,
1559
+ record: { id: '2', name: 'Bob' },
1560
+ });
1561
+
1562
+ const row = await store.load({
1563
+ tableName: snakeCaseTable as TABLE_NAMES,
1564
+ keys: { id: '2' },
1565
+ });
1566
+ expect(row?.name).toBe('Bob');
1567
+ });
1568
+ });
1569
+
1497
1570
  describe('Permission Handling', () => {
1498
1571
  const schemaRestrictedUser = 'mastra_schema_restricted_storage';
1499
1572
  const restrictedPassword = 'test123';
1500
- const testSchema = 'test_schema';
1573
+ const testSchema = 'testSchema';
1501
1574
  let adminDb: pgPromise.IDatabase<{}>;
1502
1575
  let pgpAdmin: pgPromise.IMain;
1503
1576
 
@@ -96,9 +96,14 @@ export class PostgresStore extends MastraStorage {
96
96
  }
97
97
 
98
98
  private getTableName(indexName: string) {
99
- const parsedIndexName = parseSqlIdentifier(indexName, 'table name');
100
- const parsedSchemaName = this.schema ? parseSqlIdentifier(this.schema, 'schema name') : undefined;
101
- return parsedSchemaName ? `${parsedSchemaName}."${parsedIndexName}"` : `"${parsedIndexName}"`;
99
+ const parsedIndexName = parseSqlIdentifier(indexName, 'index name');
100
+ const quotedIndexName = `"${parsedIndexName}"`;
101
+ const quotedSchemaName = this.getSchemaName();
102
+ return quotedSchemaName ? `${quotedSchemaName}.${quotedIndexName}` : quotedIndexName;
103
+ }
104
+
105
+ private getSchemaName() {
106
+ return this.schema ? `"${parseSqlIdentifier(this.schema, 'schema name')}"` : undefined;
102
107
  }
103
108
 
104
109
  /** @deprecated use getEvals instead */
@@ -311,7 +316,7 @@ export class PostgresStore extends MastraStorage {
311
316
 
312
317
  if (!schemaExists?.exists) {
313
318
  try {
314
- await this.db.none(`CREATE SCHEMA IF NOT EXISTS ${this.schema}`);
319
+ await this.db.none(`CREATE SCHEMA IF NOT EXISTS ${this.getSchemaName()}`);
315
320
  this.logger.info(`Schema "${this.schema}" created successfully`);
316
321
  } catch (error) {
317
322
  this.logger.error(`Failed to create schema "${this.schema}"`, { error });
@@ -753,7 +758,7 @@ export class PostgresStore extends MastraStorage {
753
758
  (m.row_num >= target.row_num - $${paramIdx + 3} AND m.row_num < target.row_num)
754
759
  )
755
760
  )
756
- )
761
+ ) AS query_${paramIdx}
757
762
  `, // Keep ASC for final sorting after fetching context
758
763
  );
759
764
  params.push(searchId, id, withPreviousMessages, withNextMessages);
@@ -1647,6 +1647,75 @@ describe('PgVector', () => {
1647
1647
  });
1648
1648
  });
1649
1649
 
1650
+ describe('PgVector Table Name Quoting', () => {
1651
+ const camelCaseIndex = 'TestCamelCaseIndex';
1652
+ const snakeCaseIndex = 'test_snake_case_index';
1653
+
1654
+ beforeEach(async () => {
1655
+ // Clean up any existing indexes
1656
+ try {
1657
+ await vectorDB.deleteIndex({ indexName: camelCaseIndex });
1658
+ } catch {
1659
+ // Ignore if doesn't exist
1660
+ }
1661
+ try {
1662
+ await vectorDB.deleteIndex({ indexName: snakeCaseIndex });
1663
+ } catch {
1664
+ // Ignore if doesn't exist
1665
+ }
1666
+ });
1667
+
1668
+ afterEach(async () => {
1669
+ // Clean up indexes after each test
1670
+ try {
1671
+ await vectorDB.deleteIndex({ indexName: camelCaseIndex });
1672
+ } catch {
1673
+ // Ignore if doesn't exist
1674
+ }
1675
+ try {
1676
+ await vectorDB.deleteIndex({ indexName: snakeCaseIndex });
1677
+ } catch {
1678
+ // Ignore if doesn't exist
1679
+ }
1680
+ });
1681
+
1682
+ it('should create and query a camelCase index without quoting errors', async () => {
1683
+ await expect(
1684
+ vectorDB.createIndex({
1685
+ indexName: camelCaseIndex,
1686
+ dimension: 3,
1687
+ metric: 'cosine',
1688
+ indexConfig: { type: 'hnsw' },
1689
+ }),
1690
+ ).resolves.not.toThrow();
1691
+
1692
+ const results = await vectorDB.query({
1693
+ indexName: camelCaseIndex,
1694
+ queryVector: [1, 0, 0],
1695
+ topK: 1,
1696
+ });
1697
+ expect(Array.isArray(results)).toBe(true);
1698
+ });
1699
+
1700
+ it('should create and query a snake_case index without quoting errors', async () => {
1701
+ await expect(
1702
+ vectorDB.createIndex({
1703
+ indexName: snakeCaseIndex,
1704
+ dimension: 3,
1705
+ metric: 'cosine',
1706
+ indexConfig: { type: 'hnsw' },
1707
+ }),
1708
+ ).resolves.not.toThrow();
1709
+
1710
+ const results = await vectorDB.query({
1711
+ indexName: snakeCaseIndex,
1712
+ queryVector: [1, 0, 0],
1713
+ topK: 1,
1714
+ });
1715
+ expect(Array.isArray(results)).toBe(true);
1716
+ });
1717
+ });
1718
+
1650
1719
  // Regex Operator Tests
1651
1720
  describe('Regex Operators', () => {
1652
1721
  it('should handle $regex with case sensitivity', async () => {
@@ -1878,7 +1947,7 @@ describe('PgVector', () => {
1878
1947
  });
1879
1948
 
1880
1949
  describe('Schema Support', () => {
1881
- const customSchema = 'mastra_test';
1950
+ const customSchema = 'mastraTest';
1882
1951
  let vectorDB: PgVector;
1883
1952
  let customSchemaVectorDB: PgVector;
1884
1953
 
@@ -125,8 +125,17 @@ export class PgVector extends MastraVector {
125
125
 
126
126
  private getTableName(indexName: string) {
127
127
  const parsedIndexName = parseSqlIdentifier(indexName, 'index name');
128
- const parsedSchemaName = this.schema ? parseSqlIdentifier(this.schema, 'schema name') : undefined;
129
- return parsedSchemaName ? `${parsedSchemaName}.${parsedIndexName}` : parsedIndexName;
128
+ const quotedIndexName = `"${parsedIndexName}"`;
129
+ const quotedSchemaName = this.getSchemaName();
130
+ const quotedVectorName = `"${parsedIndexName}_vector_idx"`;
131
+ return {
132
+ tableName: quotedSchemaName ? `${quotedSchemaName}.${quotedIndexName}` : quotedIndexName,
133
+ vectorIndexName: quotedVectorName,
134
+ };
135
+ }
136
+
137
+ private getSchemaName() {
138
+ return this.schema ? `"${parseSqlIdentifier(this.schema, 'schema name')}"` : undefined;
130
139
  }
131
140
 
132
141
  transformFilter(filter?: VectorFilter) {
@@ -179,7 +188,7 @@ export class PgVector extends MastraVector {
179
188
  await client.query(`SET LOCAL ivfflat.probes = ${probes}`);
180
189
  }
181
190
 
182
- const tableName = this.getTableName(indexName);
191
+ const { tableName } = this.getTableName(indexName);
183
192
 
184
193
  const query = `
185
194
  WITH vector_scores AS (
@@ -210,7 +219,7 @@ export class PgVector extends MastraVector {
210
219
  }
211
220
 
212
221
  async upsert({ indexName, vectors, metadata, ids }: UpsertVectorParams): Promise<string[]> {
213
- const tableName = this.getTableName(indexName);
222
+ const { tableName } = this.getTableName(indexName);
214
223
 
215
224
  // Start a transaction
216
225
  const client = await this.pool.connect();
@@ -289,7 +298,7 @@ export class PgVector extends MastraVector {
289
298
 
290
299
  if (!schemaExists) {
291
300
  try {
292
- await client.query(`CREATE SCHEMA IF NOT EXISTS ${this.schema}`);
301
+ await client.query(`CREATE SCHEMA IF NOT EXISTS ${this.getSchemaName()}`);
293
302
  this.logger.info(`Schema "${this.schema}" created successfully`);
294
303
  } catch (error) {
295
304
  this.logger.error(`Failed to create schema "${this.schema}"`, { error });
@@ -324,7 +333,7 @@ export class PgVector extends MastraVector {
324
333
  indexConfig = {},
325
334
  buildIndex = true,
326
335
  }: PgCreateIndexParams): Promise<void> {
327
- const tableName = this.getTableName(indexName);
336
+ const { tableName } = this.getTableName(indexName);
328
337
 
329
338
  // Validate inputs
330
339
  if (!indexName.match(/^[a-zA-Z_][a-zA-Z0-9_]*$/)) {
@@ -391,10 +400,10 @@ export class PgVector extends MastraVector {
391
400
  const mutex = this.getMutexByName(`build-${indexName}`);
392
401
  // Use async-mutex instead of advisory lock for perf (over 2x as fast)
393
402
  await mutex.runExclusive(async () => {
394
- const tableName = this.getTableName(indexName);
403
+ const { tableName, vectorIndexName } = this.getTableName(indexName);
395
404
 
396
405
  if (this.createdIndexes.has(indexName)) {
397
- await client.query(`DROP INDEX IF EXISTS ${tableName}_vector_idx`);
406
+ await client.query(`DROP INDEX IF EXISTS ${vectorIndexName}`);
398
407
  }
399
408
 
400
409
  if (indexConfig.type === 'flat') {
@@ -411,7 +420,7 @@ export class PgVector extends MastraVector {
411
420
  const efConstruction = indexConfig.hnsw?.efConstruction ?? 32;
412
421
 
413
422
  indexSQL = `
414
- CREATE INDEX IF NOT EXISTS ${indexName}_vector_idx
423
+ CREATE INDEX IF NOT EXISTS ${vectorIndexName}
415
424
  ON ${tableName}
416
425
  USING hnsw (embedding ${metricOp})
417
426
  WITH (
@@ -428,7 +437,7 @@ export class PgVector extends MastraVector {
428
437
  lists = Math.max(100, Math.min(4000, Math.floor(Math.sqrt(size) * 2)));
429
438
  }
430
439
  indexSQL = `
431
- CREATE INDEX IF NOT EXISTS ${indexName}_vector_idx
440
+ CREATE INDEX IF NOT EXISTS ${vectorIndexName}
432
441
  ON ${tableName}
433
442
  USING ivfflat (embedding ${metricOp})
434
443
  WITH (lists = ${lists});
@@ -517,7 +526,7 @@ export class PgVector extends MastraVector {
517
526
  async describeIndex({ indexName }: DescribeIndexParams): Promise<PGIndexStats> {
518
527
  const client = await this.pool.connect();
519
528
  try {
520
- const tableName = this.getTableName(indexName);
529
+ const { tableName } = this.getTableName(indexName);
521
530
 
522
531
  // Check if table exists with a vector column
523
532
  const tableExistsQuery = `
@@ -613,7 +622,7 @@ export class PgVector extends MastraVector {
613
622
  async deleteIndex({ indexName }: DeleteIndexParams): Promise<void> {
614
623
  const client = await this.pool.connect();
615
624
  try {
616
- const tableName = this.getTableName(indexName);
625
+ const { tableName } = this.getTableName(indexName);
617
626
  // Drop the table
618
627
  await client.query(`DROP TABLE IF EXISTS ${tableName} CASCADE`);
619
628
  this.createdIndexes.delete(indexName);
@@ -628,7 +637,7 @@ export class PgVector extends MastraVector {
628
637
  async truncateIndex({ indexName }: DeleteIndexParams): Promise<void> {
629
638
  const client = await this.pool.connect();
630
639
  try {
631
- const tableName = this.getTableName(indexName);
640
+ const { tableName } = this.getTableName(indexName);
632
641
  await client.query(`TRUNCATE ${tableName}`);
633
642
  } catch (e: any) {
634
643
  await client.query('ROLLBACK');
@@ -678,7 +687,7 @@ export class PgVector extends MastraVector {
678
687
  return;
679
688
  }
680
689
 
681
- const tableName = this.getTableName(indexName);
690
+ const { tableName } = this.getTableName(indexName);
682
691
 
683
692
  // query looks like this:
684
693
  // UPDATE table SET embedding = $2::vector, metadata = $3::jsonb WHERE id = $1
@@ -706,7 +715,7 @@ export class PgVector extends MastraVector {
706
715
  async deleteVector({ indexName, id }: DeleteVectorParams): Promise<void> {
707
716
  const client = await this.pool.connect();
708
717
  try {
709
- const tableName = this.getTableName(indexName);
718
+ const { tableName } = this.getTableName(indexName);
710
719
  const query = `
711
720
  DELETE FROM ${tableName}
712
721
  WHERE vector_id = $1