Merge pull request #96 from groombook/feat/impersonation-indexes-gh95

feat(db): add indexes on impersonation tables
This commit was merged in pull request #96.
This commit is contained in:
groombook-ceo[bot]
2026-03-21 23:44:18 +00:00
committed by GitHub
4 changed files with 1520 additions and 25 deletions
@@ -0,0 +1,6 @@
-- Add indexes on impersonation tables to prevent full table scans
-- Ref: GitHub #95
CREATE INDEX "impersonation_sessions_staff_id_status_idx" ON "impersonation_sessions" USING btree ("staff_id","status");--> statement-breakpoint
CREATE INDEX "impersonation_sessions_client_id_idx" ON "impersonation_sessions" USING btree ("client_id");--> statement-breakpoint
CREATE INDEX "impersonation_audit_logs_session_id_idx" ON "impersonation_audit_logs" USING btree ("session_id");
File diff suppressed because it is too large Load Diff
@@ -78,6 +78,13 @@
"when": 1742500800000, "when": 1742500800000,
"tag": "0010_impersonation_sessions", "tag": "0010_impersonation_sessions",
"breakpoints": true "breakpoints": true
},
{
"idx": 11,
"version": "7",
"when": 1742587200000,
"tag": "0011_impersonation_indexes",
"breakpoints": true
} }
] ]
} }
+39 -25
View File
@@ -1,5 +1,6 @@
import { import {
boolean, boolean,
index,
integer, integer,
jsonb, jsonb,
numeric, numeric,
@@ -232,32 +233,45 @@ export const impersonationSessionStatusEnum = pgEnum(
["active", "ended", "expired"] ["active", "ended", "expired"]
); );
export const impersonationSessions = pgTable("impersonation_sessions", { export const impersonationSessions = pgTable(
id: uuid("id").primaryKey().defaultRandom(), "impersonation_sessions",
staffId: uuid("staff_id") {
.notNull() id: uuid("id").primaryKey().defaultRandom(),
.references(() => staff.id, { onDelete: "restrict" }), staffId: uuid("staff_id")
clientId: uuid("client_id") .notNull()
.notNull() .references(() => staff.id, { onDelete: "restrict" }),
.references(() => clients.id, { onDelete: "restrict" }), clientId: uuid("client_id")
reason: text("reason"), .notNull()
status: impersonationSessionStatusEnum("status").notNull().default("active"), .references(() => clients.id, { onDelete: "restrict" }),
startedAt: timestamp("started_at").notNull().defaultNow(), reason: text("reason"),
endedAt: timestamp("ended_at"), status: impersonationSessionStatusEnum("status")
expiresAt: timestamp("expires_at").notNull(), .notNull()
createdAt: timestamp("created_at").notNull().defaultNow(), .default("active"),
}); startedAt: timestamp("started_at").notNull().defaultNow(),
endedAt: timestamp("ended_at"),
expiresAt: timestamp("expires_at").notNull(),
createdAt: timestamp("created_at").notNull().defaultNow(),
},
(t) => [
index("impersonation_sessions_staff_id_status_idx").on(t.staffId, t.status),
index("impersonation_sessions_client_id_idx").on(t.clientId),
]
);
export const impersonationAuditLogs = pgTable("impersonation_audit_logs", { export const impersonationAuditLogs = pgTable(
id: uuid("id").primaryKey().defaultRandom(), "impersonation_audit_logs",
sessionId: uuid("session_id") {
.notNull() id: uuid("id").primaryKey().defaultRandom(),
.references(() => impersonationSessions.id, { onDelete: "cascade" }), sessionId: uuid("session_id")
action: text("action").notNull(), .notNull()
pageVisited: text("page_visited"), .references(() => impersonationSessions.id, { onDelete: "cascade" }),
metadata: jsonb("metadata").$type<Record<string, unknown>>(), action: text("action").notNull(),
createdAt: timestamp("created_at").notNull().defaultNow(), pageVisited: text("page_visited"),
}); metadata: jsonb("metadata").$type<Record<string, unknown>>(),
createdAt: timestamp("created_at").notNull().defaultNow(),
},
(t) => [index("impersonation_audit_logs_session_id_idx").on(t.sessionId)]
);
export const businessSettings = pgTable("business_settings", { export const businessSettings = pgTable("business_settings", {
id: uuid("id").primaryKey().defaultRandom(), id: uuid("id").primaryKey().defaultRandom(),