fix(oceanbase): localize explain plan estimated time label
This commit is contained in:
1 parent
ce2d270132
commit
98b7a9ed75
18 files changed
+119
-16
No files matched your search
@@ -4,6 +4,7 @@ import { useI18n } from "vue-i18n";
|
||||
import { ArrowDownWideNarrow, CircleHelp, GitMerge, KeyRound, Layers, ListTree, Maximize2, MonitorCheck, Pencil, Sigma, Split, Table2, ZoomIn, ZoomOut } from "@lucide/vue";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import type { ExplainPlanNode } from "@/lib/diagram/explainPlan";
|
||||
import { formatExplainPlanDetails } from "@/lib/diagram/explainPlan";
|
||||
import type { PlanCanvasCategory, PlanCanvasNode } from "@/lib/diagram/planCanvas";
|
||||
import { buildPlanCanvas, edgeStrokeWidth, formatPlanRows, heatLevel, PLAN_CANVAS_GAP_X, PLAN_CANVAS_NODE_H, PLAN_CANVAS_NODE_W } from "@/lib/diagram/planCanvas";
|
||||
|
||||
@@ -110,7 +111,7 @@ interface DetailEntry {
|
||||
}
|
||||
|
||||
const selectedDetails = computed<DetailEntry[]>(() =>
|
||||
(selected.value?.node.details ?? [])
|
||||
formatExplainPlanDetails(selected.value?.node, t("explain.estimatedTime"))
|
||||
.map((detail): DetailEntry => {
|
||||
const separatorIndex = detail.indexOf(":");
|
||||
if (separatorIndex === -1) return { value: detail.trim() };
|
||||
|
||||
@@ -5,6 +5,7 @@ import { useI18n } from "vue-i18n";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
|
||||
import type { ExplainPlanNode } from "@/lib/diagram/explainPlan";
|
||||
import { formatExplainPlanDetails } from "@/lib/diagram/explainPlan";
|
||||
|
||||
const props = defineProps<{
|
||||
node: ExplainPlanNode;
|
||||
@@ -20,7 +21,7 @@ interface ExplainPlanDetailEntry {
|
||||
}
|
||||
|
||||
const detailEntries = computed<ExplainPlanDetailEntry[]>(() =>
|
||||
props.node.details
|
||||
formatExplainPlanDetails(props.node, t("explain.estimatedTime"))
|
||||
.map((detail): ExplainPlanDetailEntry => {
|
||||
const separatorIndex = detail.indexOf(":");
|
||||
if (separatorIndex === -1) return { value: detail.trim() };
|
||||
|
||||
@@ -3,7 +3,7 @@ import { computed, ref, watch } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { AlertCircle, Braces, GitBranch, Table2, FileText, Workflow } from "@lucide/vue";
|
||||
import type { ParsedExplainPlan, ExplainPlanNode } from "@/lib/diagram/explainPlan";
|
||||
import { flattenExplainPlanNodes } from "@/lib/diagram/explainPlan";
|
||||
import { flattenExplainPlanNodes, formatExplainPlanDetails } from "@/lib/diagram/explainPlan";
|
||||
import { extractActualRows } from "@/lib/diagram/planCanvas";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import type { QueryResult } from "@/types/database";
|
||||
@@ -185,7 +185,7 @@ function tableCellText(value: unknown): string {
|
||||
<td class="px-2 py-1.5 tabular-nums">{{ row.node.cost || "-" }}</td>
|
||||
<td class="px-2 py-1.5 tabular-nums">{{ row.node.rows || "-" }}</td>
|
||||
<td class="px-2 py-1.5 text-muted-foreground">
|
||||
{{ row.node.details.join("; ") || "-" }}
|
||||
{{ formatExplainPlanDetails(row.node, t("explain.estimatedTime")).join("; ") || "-" }}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
// @vitest-environment happy-dom
|
||||
|
||||
import { afterEach, describe, expect, it } from "vitest";
|
||||
import { createApp, nextTick, type App } from "vue";
|
||||
import { createI18n } from "vue-i18n";
|
||||
import en from "@/i18n/locales/en";
|
||||
import zhCN from "@/i18n/locales/zh-CN";
|
||||
import { parseExplainResult } from "@/lib/diagram/explainPlan";
|
||||
import ExplainPlanViewer from "@/components/explain/ExplainPlanViewer.vue";
|
||||
|
||||
let app: App | undefined;
|
||||
|
||||
afterEach(() => {
|
||||
app?.unmount();
|
||||
app = undefined;
|
||||
document.body.innerHTML = "";
|
||||
});
|
||||
|
||||
describe("OceanBase estimated time localization", () => {
|
||||
it.each(["canvas", "tree", "summary"] as const)("updates the existing %s view when the locale changes", async (view) => {
|
||||
const plan = parseExplainResult("oceanbase-oracle", {
|
||||
columns: ["Query Plan"],
|
||||
rows: [[JSON.stringify({ ID: 0, OPERATOR: "TABLE FULL SCAN", NAME: "EXAMPLE_TABLE", "EST.TIME(us)": 0, filter: "C1 > 4" })]],
|
||||
affected_rows: 0,
|
||||
execution_time_ms: 1,
|
||||
});
|
||||
const originalPlan = JSON.stringify(plan);
|
||||
const i18n = createI18n({ legacy: false, locale: "en", messages: { en, "zh-CN": zhCN } });
|
||||
const container = document.createElement("div");
|
||||
document.body.append(container);
|
||||
app = createApp(ExplainPlanViewer, { plan });
|
||||
app.use(i18n);
|
||||
app.mount(container);
|
||||
await nextTick();
|
||||
|
||||
if (view !== "canvas") {
|
||||
const label = en.explain[view];
|
||||
const button = [...container.querySelectorAll("button")].find((item) => item.textContent?.trim() === label);
|
||||
expect(button).toBeDefined();
|
||||
button!.click();
|
||||
await nextTick();
|
||||
}
|
||||
|
||||
expect(container.textContent).toContain("Estimated time");
|
||||
expect(container.textContent).toContain("0 µs");
|
||||
expect(container.textContent).toContain("C1 > 4");
|
||||
|
||||
i18n.global.locale.value = "zh-CN";
|
||||
await nextTick();
|
||||
expect(container.textContent).toContain("预计耗时");
|
||||
expect(container.textContent).not.toContain("Estimated time");
|
||||
expect(container.textContent).toContain("0 µs");
|
||||
expect(container.textContent).toContain("C1 > 4");
|
||||
|
||||
i18n.global.locale.value = "en";
|
||||
await nextTick();
|
||||
expect(container.textContent).toContain("Estimated time");
|
||||
expect(container.textContent).not.toContain("预计耗时");
|
||||
expect(JSON.stringify(plan)).toBe(originalPlan);
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user