Repository: ponder-sh/ponder (ts)

Issue:
bug: duplicate SQL table names are not validated
We implicitly validate against duplicate JS table names, but because you can pass a custom SQL table name to `onchainTable` we can end up with duplicates. This breaks important invariants including a known crash when reverting operations after a reorg.

We should add an explicit validation during the build step.

Pull request description:
add validation for duplicate table names
Closes #1638 

Patch:
diff --git a/.changeset/fifty-moose-speak.md b/.changeset/fifty-moose-speak.md
new file mode 100644
index 00000000..480f0fa6
--- /dev/null
+++ b/.changeset/fifty-moose-speak.md
@@ -0,0 +1,5 @@
+---
+"ponder": patch
+---
+
+Added validation for schemas with duplicate table names.
diff --git a/packages/core/src/build/schema.ts b/packages/core/src/build/schema.ts
index 13e400f1..7f22181e 100644
--- a/packages/core/src/build/schema.ts
+++ b/packages/core/src/build/schema.ts
@@ -1,7 +1,7 @@
 import { getSql } from "@/drizzle/kit/index.js";
 import { BuildError } from "@/internal/errors.js";
 import type { Schema } from "@/internal/types.js";
-import { SQL, getTableColumns, is } from "drizzle-orm";
+import { SQL, getTableColumns, getTableName, is } from "drizzle-orm";
 import {
   PgBigSerial53,
   PgBigSerial64,
@@ -16,6 +16,8 @@ import {
 export const buildSchema = ({ schema }: { schema: Schema }) => {
   const statements = getSql(schema);
 
+  const tableNames = new Set<string>();
+
   for (const [name, s] of Object.entries(schema)) {
     if (is(s, PgTable)) {
       let hasPrimaryKey = false;
@@ -81,6 +83,14 @@ export const buildSchema = ({ schema }: { schema: Schema }) => {
         }
       }
 
+      if (tableNames.has(getTableName(s))) {
+        throw new Error(
+          `Schema validation failed: table name '${getTableName(s)}' is used multiple times.`,
+        );
+      } else {
+        tableNames.add(getTableName(s));
+      }
+
       if (getTableConfig(s).primaryKeys.length > 1) {
         throw new Error(
           `Schema validation failed: '${name}' has multiple primary keys.`,


Test patch:
diff --git a/packages/core/src/build/schema.test.ts b/packages/core/src/build/schema.test.ts
index d251c677..1a26356f 100644
--- a/packages/core/src/build/schema.test.ts
+++ b/packages/core/src/build/schema.test.ts
@@ -220,3 +220,16 @@ test("buildScheama() success with enum", () => {
 
   buildSchema({ schema });
 });
+
+test("buildScheama() duplicate table name", () => {
+  const schema = {
+    account: onchainTable("account", (p) => ({
+      address: p.hex().primaryKey(),
+    })),
+    account2: onchainTable("account", (p) => ({
+      address: p.hex().primaryKey(),
+    })),
+  };
+
+  expect(() => buildSchema({ schema })).toThrowError();
+});