import "dotenv/config" import { drizzle } from "drizzle-orm/node-postgres" import { sql } from "drizzle-orm" import { Pool } from "pg" import { loadSecrets, secrets } from "../src/utils/secrets" async function run() { let connectionString = process.env.DATABASE_URL if (!connectionString) { await loadSecrets() connectionString = secrets.DATABASE_URL } if (!connectionString) { throw new Error("DATABASE_URL not configured") } const pool = new Pool({ connectionString, max: 1, connectionTimeoutMillis: 10000, }) try { const db = drizzle(pool) const duplicates = await db.execute(sql` SELECT tenant_id, user_id, count(*)::int AS count FROM auth_tenant_users GROUP BY tenant_id, user_id HAVING count(*) > 1 ORDER BY count(*) DESC; `) console.log(`Gefundene doppelte Tenant-Zuordnungen: ${duplicates.rows.length}`) for (const row of duplicates.rows as Record[]) { console.log(JSON.stringify(row)) } const deleted = await db.execute(sql` DELETE FROM auth_tenant_users duplicate USING auth_tenant_users keep WHERE duplicate.tenant_id = keep.tenant_id AND duplicate.user_id = keep.user_id AND duplicate.ctid > keep.ctid; `) console.log(`Entfernte doppelte Zeilen: ${deleted.rowCount || 0}`) await db.execute(sql` CREATE UNIQUE INDEX IF NOT EXISTS auth_tenant_users_tenant_user_unique ON auth_tenant_users (tenant_id, user_id); `) console.log("Unique Index auth_tenant_users_tenant_user_unique ist vorhanden") } finally { await pool.end() } } run().catch((err) => { console.error("Dedupe auth_tenant_users failed") console.error(err) process.exit(1) })