feat: add cross-database entity lookup for searching column values across all databases

Enables searching for a specific column value (e.g. carrier_id=123) across all databases on a PostgreSQL server. The backend creates temporary connection pools per database (semaphore-limited to 5), queries information_schema for matching columns, and executes read-only SELECTs with real-time progress events. Results are grouped by database/table in a new "Entity Lookup" tab.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-13 17:28:33 +03:00
parent a2371f00df
commit d5cff8bd5e
13 changed files with 1030 additions and 5 deletions

View File

@@ -8,7 +8,7 @@ import { ReadOnlyToggle } from "@/components/layout/ReadOnlyToggle";
import { useAppStore } from "@/stores/app-store";
import { useConnections, useReconnect } from "@/hooks/use-connections";
import { toast } from "sonner";
import { Database, Plus, RefreshCw } from "lucide-react";
import { Database, Plus, RefreshCw, Search } from "lucide-react";
import type { ConnectionConfig, Tab } from "@/types";
import { getEnvironment } from "@/lib/environment";
@@ -16,7 +16,7 @@ export function Toolbar() {
const [listOpen, setListOpen] = useState(false);
const [dialogOpen, setDialogOpen] = useState(false);
const [editingConn, setEditingConn] = useState<ConnectionConfig | null>(null);
const { activeConnectionId, addTab } = useAppStore();
const { activeConnectionId, currentDatabase, addTab } = useAppStore();
const { data: connections } = useConnections();
const reconnectMutation = useReconnect();
const activeConn = connections?.find((c) => c.id === activeConnectionId);
@@ -38,11 +38,24 @@ export function Toolbar() {
type: "query",
title: "New Query",
connectionId: activeConnectionId,
database: currentDatabase ?? undefined,
sql: "",
};
addTab(tab);
};
const handleNewLookup = () => {
if (!activeConnectionId) return;
const tab: Tab = {
id: crypto.randomUUID(),
type: "lookup",
title: "Entity Lookup",
connectionId: activeConnectionId,
database: currentDatabase ?? undefined,
};
addTab(tab);
};
return (
<>
<div
@@ -91,6 +104,17 @@ export function Toolbar() {
New Query
</Button>
<Button
variant="ghost"
size="sm"
className="h-7 gap-1.5"
onClick={handleNewLookup}
disabled={!activeConnectionId}
>
<Search className="h-3.5 w-3.5" />
Entity Lookup
</Button>
<div className="flex-1" />
<span className="text-xs font-semibold text-muted-foreground tracking-wide">