diff --git a/apps/webapp/app/v3/querySchemas.ts b/apps/webapp/app/v3/querySchemas.ts index c4fdd767a..14acbfad0 100644 --- a/apps/webapp/app/v3/querySchemas.ts +++ b/apps/webapp/app/v3/querySchemas.ts @@ -6,11 +6,6 @@ import { runFriendlyStatus, runStatusTitleFromStatus } from "~/components/runs/v */ const ENVIRONMENT_TYPES = ["PRODUCTION", "STAGING", "DEVELOPMENT", "PREVIEW"] as const; -/** - * Engine type values - */ -const ENGINE_TYPES = ["V1", "V2"] as const; - /** * Machine preset values */ @@ -37,14 +32,10 @@ export const runsSchema: TableSchema = { environmentId: "environment_id", }, columns: { - // IDs & hierarchy run_id: { name: "run_id", - ...column("String", { description: "Unique run identifier" }), - }, - friendly_id: { - name: "friendly_id", - ...column("String", { description: "Human-readable run ID (e.g., run_abc123)" }), + clickhouseName: "friendly_id", + ...column("String", { description: "Run ID (e.g., run_abc123)" }), }, environment_id: { name: "environment_id", @@ -67,16 +58,7 @@ export const runsSchema: TableSchema = { }, attempt: { name: "attempt", - ...column("UInt8", { description: "Attempt number (starts at 1)" }), - }, - - // Status & engine - engine: { - name: "engine", - ...column("LowCardinality(String)", { - description: "Run engine version", - allowedValues: [...ENGINE_TYPES], - }), + ...column("UInt8", { description: "Number of attempts (starts at 1)" }), }, status: { name: "status", @@ -208,7 +190,7 @@ export const runsSchema: TableSchema = { // Tags & versions tags: { name: "tags", - ...column("Array(String)", { description: "Run tags" }), + ...column("Array(String)", { description: "Run tags", customRenderType: "tags" }), }, task_version: { name: "task_version", @@ -227,6 +209,7 @@ export const runsSchema: TableSchema = { ...column("LowCardinality(String)", { description: "Machine preset", allowedValues: [...MACHINE_PRESETS], + customRenderType: "machine", }), }, @@ -235,6 +218,15 @@ export const runsSchema: TableSchema = { name: "is_test", ...column("UInt8", { description: "Whether this is a test run (0 or 1)" }), }, + + // Virtual columns + execution_duration: { + name: "execution_duration", + ...column("Nullable(Int64)", { + description: "Computed execution time in milliseconds (virtual column)", + }), + expression: "dateDiff('millisecond', started_at, completed_at)", + }, }, }; @@ -248,7 +240,6 @@ export const querySchemas: TableSchema[] = [runsSchema]; */ export const defaultQuery = `SELECT run_id, - friendly_id, task_identifier, status, created_at, diff --git a/internal-packages/tsql/src/query/printer.test.ts b/internal-packages/tsql/src/query/printer.test.ts index 6825e31da..57b4051b3 100644 --- a/internal-packages/tsql/src/query/printer.test.ts +++ b/internal-packages/tsql/src/query/printer.test.ts @@ -209,6 +209,46 @@ describe("ClickHousePrinter", () => { expect(sql).toContain("run_id"); expect(sql).toContain("created_at"); }); + + it("should add AS alias for columns with different clickhouseName to preserve user-facing name in results", () => { + const ctx = createMappedContext(); + const { sql, columns } = printQuery("SELECT id, created, status FROM runs", ctx); + + // Columns with clickhouseName should be aliased back to user-facing name + // id -> run_id AS id, created -> created_at AS created + expect(sql).toContain("run_id AS id"); + expect(sql).toContain("created_at AS created"); + // status has no clickhouseName mapping, should not have alias + expect(sql).not.toContain("status AS"); + + // Column metadata should use user-facing names + expect(columns.map((c) => c.name)).toEqual(["id", "created", "status"]); + }); + + it("should add AS alias for qualified column references with different clickhouseName", () => { + const ctx = createMappedContext(); + const { sql, columns } = printQuery("SELECT runs.id, runs.task FROM runs", ctx); + + // Should add aliases to preserve user-facing names + expect(sql).toContain("run_id AS id"); + expect(sql).toContain("task_identifier AS task"); + + // Column metadata should use user-facing names + expect(columns.map((c) => c.name)).toEqual(["id", "task"]); + }); + + it("should not add redundant alias when user provides explicit AS", () => { + const ctx = createMappedContext(); + const { sql, columns } = printQuery("SELECT id AS my_id FROM runs", ctx); + + // Should use the clickhouse name with user's explicit alias + expect(sql).toContain("run_id AS my_id"); + // Should NOT have double aliasing + expect(sql).not.toContain("run_id AS id AS my_id"); + + // Column metadata should use the explicit alias + expect(columns.map((c) => c.name)).toEqual(["my_id"]); + }); }); describe("WHERE clauses", () => { diff --git a/internal-packages/tsql/src/query/printer.ts b/internal-packages/tsql/src/query/printer.ts index 082e9fee2..e8c1de7e7 100644 --- a/internal-packages/tsql/src/query/printer.ts +++ b/internal-packages/tsql/src/query/printer.ts @@ -479,7 +479,16 @@ export class ClickHousePrinter { // Add the alias to preserve the column name sqlResult = `${visited} AS ${this.printIdentifier(virtualColumnName)}`; } else { - sqlResult = this.visit(col); + // Visit the field to get the ClickHouse SQL + const visited = this.visit(col); + + // Check if the column has a different clickhouseName - if so, add an alias + // to ensure results come back with the user-facing name + if (outputName && sourceColumn?.clickhouseName && sourceColumn.clickhouseName !== outputName) { + sqlResult = `${visited} AS ${this.printIdentifier(outputName)}`; + } else { + sqlResult = visited; + } } } else { // For non-virtual columns or expressions already wrapped in Alias, visit normally