fix(databases): execute exact row count fallback for empty tables and tighten table spacing
This commit is contained in:
@@ -232,7 +232,7 @@ function formatCount(n: number) {
|
|||||||
const treeWrap: React.CSSProperties = {
|
const treeWrap: React.CSSProperties = {
|
||||||
display: "flex",
|
display: "flex",
|
||||||
flexDirection: "column",
|
flexDirection: "column",
|
||||||
gap: 6,
|
gap: 0,
|
||||||
};
|
};
|
||||||
const list: React.CSSProperties = {
|
const list: React.CSSProperties = {
|
||||||
listStyle: "none",
|
listStyle: "none",
|
||||||
@@ -240,14 +240,14 @@ const list: React.CSSProperties = {
|
|||||||
padding: 0,
|
padding: 0,
|
||||||
display: "flex",
|
display: "flex",
|
||||||
flexDirection: "column",
|
flexDirection: "column",
|
||||||
gap: 1,
|
gap: 0,
|
||||||
};
|
};
|
||||||
const row: React.CSSProperties = {
|
const row: React.CSSProperties = {
|
||||||
display: "flex",
|
display: "flex",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
gap: 8,
|
gap: 8,
|
||||||
width: "100%",
|
width: "100%",
|
||||||
padding: "6px 8px 6px 6px",
|
padding: "4px 8px 4px 6px",
|
||||||
border: "1px solid transparent",
|
border: "1px solid transparent",
|
||||||
borderRadius: THEME.radiusSm,
|
borderRadius: THEME.radiusSm,
|
||||||
cursor: "pointer",
|
cursor: "pointer",
|
||||||
|
|||||||
@@ -124,6 +124,52 @@ async function pgListTables(container: string): Promise<IntrospectedTable[]> {
|
|||||||
});
|
});
|
||||||
if (all.length >= MAX_TABLES) break;
|
if (all.length >= MAX_TABLES) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ── Exact-count fallback for unanalyzed tables ──
|
||||||
|
// If Postgres reports 0 rows (usually because the table is new and hasn't
|
||||||
|
// been analyzed yet), we run a fast exact COUNT(*) just for those tables
|
||||||
|
// so the UI doesn't falsely report '0' when there is real data.
|
||||||
|
const suspectTables = all.filter(
|
||||||
|
(t) =>
|
||||||
|
t.approxRows === 0 && (multi ? t.schema.startsWith(`${db}.`) : true),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (suspectTables.length > 0) {
|
||||||
|
const unionQueries = suspectTables.map((t) => {
|
||||||
|
const rawSchema = multi ? t.schema.split(".")[1] : t.schema;
|
||||||
|
return `SELECT '${rawSchema}|${t.name}|' || count(*) FROM "${rawSchema}"."${t.name}"`;
|
||||||
|
});
|
||||||
|
|
||||||
|
const exactQuery = unionQueries.join(" UNION ALL ");
|
||||||
|
const exactCmd =
|
||||||
|
`docker exec ${sq(container)} bash -c ` +
|
||||||
|
sq(
|
||||||
|
`psql -U "$POSTGRES_USER" -d ${sqInner(db)} -tAF '|' -c ${sqInner(exactQuery)}`,
|
||||||
|
);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const exactRes = await runOnCoolifyHost(exactCmd, {
|
||||||
|
timeoutMs: SSH_TIMEOUT_MS,
|
||||||
|
});
|
||||||
|
if (exactRes.code === 0) {
|
||||||
|
const exactMap = new Map<string, number>();
|
||||||
|
for (const line of exactRes.stdout.split("\n")) {
|
||||||
|
const [sch, nm, cnt] = line.trim().split("|");
|
||||||
|
if (sch && nm && cnt) exactMap.set(`${sch}.${nm}`, Number(cnt));
|
||||||
|
}
|
||||||
|
for (const t of suspectTables) {
|
||||||
|
const rawSchema = multi ? t.schema.split(".")[1] : t.schema;
|
||||||
|
const exactCount = exactMap.get(`${rawSchema}.${t.name}`);
|
||||||
|
if (exactCount !== undefined) {
|
||||||
|
t.approxRows = exactCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
// Fall back to 0 if the exact count fails for any reason
|
||||||
|
console.warn("[db-introspect] Failed to fetch exact counts:", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return all.slice(0, MAX_TABLES);
|
return all.slice(0, MAX_TABLES);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user