Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@ auto-generated per-PR notes; this file is the curated, human-readable history.
flashes its chevron shut and back open (`src/ui/schema.js`).

### Added
- **KPI panels now render one-row scalar and named-tuple results** (#154) in
both the workbench and Dashboard through one shared reader and renderer.
The canonical Presentation Spec supports exact-name field metadata, nested
delta display semantics, units, rounding, colors, NULL text, and visibility;
explicit KPI queries own typed progress streaming and reject authored
trailing `FORMAT` clauses before sending a request.
- **The saved-query Spec editor now provides complete schema-driven native
CodeMirror autocomplete** (#221). Root/nested properties, discriminated panel
branches, constants, enums, booleans, nullable values, defaults, examples,
Expand Down
27 changes: 27 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,33 @@ saved-query and Library envelopes plus the offline schema bundle. Its toolbar is
**Save**, and the **SQL | Spec** switch. Blocking errors disable Save and are
never persisted; unknown fields remain valid and survive Save.

The implemented **KPI** panel turns an exactly-one-row result into responsive
cards: numeric scalar columns become simple KPIs, while named ClickHouse
`Tuple(value numeric, delta Nullable(numeric))` columns add an optional delta.
SQL owns the values; `panel.fieldConfig` owns labels, descriptions, units,
rounding, colors, NULL text, visibility, and delta semantics. The complete
[`kpi-panel.json`](examples/kpi-panel.json) Library example can be opened from
**File ▾ → Open** and renders identically in the workbench and Dashboard.
When constructing a named tuple from expressions, either enable alias-derived
member names for the query:

```sql
SELECT (99.95 AS value, 0.08 AS delta) AS availability
SETTINGS enable_named_columns_in_function_tuple = 1
```

or cast an ordinary tuple to an explicitly named type:

```sql
SELECT CAST(
(99.95, 0.08),
'Tuple(value Float64, delta Float64)'
) AS availability
```

Without the setting or cast, ClickHouse reports `Tuple(Float64, Float64)`,
which is positional and intentionally ineligible for KPI value/delta roles.

Panel controls and Library favorite/pencil edits merge their fields into valid
open Spec drafts, preserving unrelated unsaved and extension fields. Syntax or
schema/feature errors block the staged writer before any draft or Library entry
Expand Down
9 changes: 0 additions & 9 deletions docs/drafts/query-presentation-spec-next.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -692,15 +692,6 @@
"properties": {
"type": {
"const": "kpi"
},
"layout": {
"type": "string",
"enum": [
"auto",
"row",
"grid"
],
"default": "auto"
}
},
"additionalProperties": true,
Expand Down
19 changes: 18 additions & 1 deletion docs/drafts/visualization-spec-authoring-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ SELECT
12.4 AS value,
-1.7 AS delta
) AS cancellation_rate
SETTINGS enable_named_columns_in_function_tuple = 1
```

The top-level column is `cancellation_rate`. Its runtime object is:
Expand All @@ -170,12 +171,27 @@ The top-level column is `cancellation_rate`. Its runtime object is:
}
```

ClickHouse 24.7+ supports constructing a named tuple by aliasing tuple elements:
ClickHouse can construct a named tuple from aliased tuple elements when the
query enables named columns for the `tuple` function:

```sql
(expr AS member_name, expr AS another_member) AS result_column
SETTINGS enable_named_columns_in_function_tuple = 1
```

Alternatively, cast a positional tuple to an explicitly named tuple type:

```sql
CAST(
(expr, another_expr),
'Tuple(member_name Float64, another_member Float64)'
) AS result_column
```

Aliasing tuple elements without the setting does not establish the result type
contract: ClickHouse reports a positional type such as
`Tuple(Float64, Float64)`.

Only **named** tuples are used as visual-object contracts. Positional tuples such as `(12.4, -1.7)` are ambiguous and MUST NOT be interpreted by member position.

### 3.4 One-row versus row-oriented panels
Expand Down Expand Up @@ -527,6 +543,7 @@ SELECT
87.2 AS value,
2.3 AS delta
) AS on_time_rate
SETTINGS enable_named_columns_in_function_tuple = 1
```

### Spec
Expand Down
35 changes: 35 additions & 0 deletions examples/kpi-panel.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"$schema": "https://altinity.com/schemas/altinity-sql-browser/library-v2.schema.json",
"format": "altinity-sql-browser/saved-queries",
"version": 2,
"exportedAt": "2026-07-14T00:00:00.000Z",
"queries": [
{
"id": "kpi-service-health",
"sql": "SELECT count() AS active_users, (99.95 AS value, 0.08 AS delta) AS availability SETTINGS enable_named_columns_in_function_tuple = 1",
"specVersion": 1,
"spec": {
"name": "Service KPIs",
"description": "Scalar and named-tuple KPI cards from one SQL row.",
"favorite": true,
"view": "panel",
"panel": {
"cfg": { "type": "kpi" },
"fieldConfig": {
"defaults": { "noValue": "—" },
"columns": {
"active_users": { "displayName": "Active users", "color": "#4f8cff" },
"availability": {
"displayName": "Availability",
"description": "Current service availability.",
"unit": "%",
"decimals": 2,
"delta": { "unit": " pp", "decimals": 2, "positiveIsGood": true }
}
}
}
}
}
}
]
}
120 changes: 116 additions & 4 deletions schemas/generated/library-v2.bundle.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,56 @@
"source": "resultColumnIndexes"
}
},
"deltaPresentation": {
"title": "Delta presentation",
"description": "Display metadata for a runtime KPI delta value.",
"type": "object",
"properties": {
"displayName": {
"title": "Delta label",
"description": "Optional visible label for the delta.",
"type": "string"
},
"unit": {
"title": "Delta unit",
"description": "Display-only suffix appended to the delta.",
"type": "string"
},
"decimals": {
"title": "Delta decimal places",
"description": "Requested display rounding for the delta.",
"type": "integer",
"minimum": 0,
"maximum": 20,
"default": 0,
"examples": [
1
]
},
"positiveIsGood": {
"title": "Positive is good",
"description": "Whether a positive runtime delta has good semantics.",
"type": "boolean"
},
"show": {
"title": "Show delta",
"description": "Whether a present runtime delta is rendered.",
"type": "boolean",
"default": true
}
},
"additionalProperties": true,
"x-altinity-order": [
"displayName",
"unit",
"decimals",
"positiveIsGood",
"show"
]
},
"fieldConfigValue": {
"title": "Field display configuration",
"description": "Known display metadata for one result column. Unknown renderer extensions are retained.",
"title": "Field presentation metadata",
"description": "Known presentation metadata for one result column. Unknown renderer extensions are retained.",
"type": "object",
"properties": {
"displayName": {
Expand All @@ -93,13 +140,57 @@
"title": "Decimal places",
"description": "Requested number of decimal places for numeric display.",
"type": "integer",
"default": 0
"minimum": 0,
"maximum": 20,
"default": 0,
"examples": [
2
]
},
"description": {
"title": "Description",
"description": "Supporting display text for the field.",
"type": "string"
},
"unit": {
"title": "Unit",
"description": "Display-only suffix appended to the value.",
"type": "string",
"examples": [
"%"
]
},
"color": {
"title": "Color",
"description": "Theme token or CSS color hint interpreted by the renderer.",
"type": "string"
},
"noValue": {
"title": "No-value text",
"description": "Text shown for NULL or unavailable values.",
"type": "string",
"default": "—"
},
"hidden": {
"title": "Hidden",
"description": "Suppress this otherwise eligible result field.",
"type": "boolean",
"default": false
},
"delta": {
"$ref": "#/$defs/deltaPresentation"
}
},
"additionalProperties": true,
"x-altinity-order": [
"displayName",
"decimals"
"description",
"unit",
"decimals",
"color",
"noValue",
"hidden",
"delta"
]
},
"fieldConfig": {
Expand Down Expand Up @@ -388,6 +479,26 @@
}
]
},
{
"title": "KPI",
"description": "One-row scalar and named-tuple KPI cards.",
"x-altinity-status": "implemented",
"x-altinity-snippet": {
"type": "kpi"
},
"properties": {
"type": {
"const": "kpi"
}
},
"required": [
"type"
],
"additionalProperties": true,
"x-altinity-order": [
"type"
]
},
{
"title": "Table",
"description": "Tabular result rendering with no required panel-specific fields.",
Expand Down Expand Up @@ -486,6 +597,7 @@
"line",
"area",
"pie",
"kpi",
"table",
"logs",
"text"
Expand Down
45 changes: 39 additions & 6 deletions schemas/query-spec-v1.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,23 @@
"minimum": 0,
"x-altinity-completion": { "source": "resultColumnIndexes" }
},
"deltaPresentation": {
"title": "Delta presentation",
"description": "Display metadata for a runtime KPI delta value.",
"type": "object",
"properties": {
"displayName": { "title": "Delta label", "description": "Optional visible label for the delta.", "type": "string" },
"unit": { "title": "Delta unit", "description": "Display-only suffix appended to the delta.", "type": "string" },
"decimals": { "title": "Delta decimal places", "description": "Requested display rounding for the delta.", "type": "integer", "minimum": 0, "maximum": 20, "default": 0, "examples": [1] },
"positiveIsGood": { "title": "Positive is good", "description": "Whether a positive runtime delta has good semantics.", "type": "boolean" },
"show": { "title": "Show delta", "description": "Whether a present runtime delta is rendered.", "type": "boolean", "default": true }
},
"additionalProperties": true,
"x-altinity-order": ["displayName", "unit", "decimals", "positiveIsGood", "show"]
},
"fieldConfigValue": {
"title": "Field display configuration",
"description": "Known display metadata for one result column. Unknown renderer extensions are retained.",
"title": "Field presentation metadata",
"description": "Known presentation metadata for one result column. Unknown renderer extensions are retained.",
"type": "object",
"properties": {
"displayName": {
Expand All @@ -67,11 +81,20 @@
"title": "Decimal places",
"description": "Requested number of decimal places for numeric display.",
"type": "integer",
"default": 0
}
"minimum": 0,
"maximum": 20,
"default": 0,
"examples": [2]
},
"description": { "title": "Description", "description": "Supporting display text for the field.", "type": "string" },
"unit": { "title": "Unit", "description": "Display-only suffix appended to the value.", "type": "string", "examples": ["%"] },
"color": { "title": "Color", "description": "Theme token or CSS color hint interpreted by the renderer.", "type": "string" },
"noValue": { "title": "No-value text", "description": "Text shown for NULL or unavailable values.", "type": "string", "default": "—" },
"hidden": { "title": "Hidden", "description": "Suppress this otherwise eligible result field.", "type": "boolean", "default": false },
"delta": { "$ref": "#/$defs/deltaPresentation" }
},
"additionalProperties": true,
"x-altinity-order": ["displayName", "decimals"]
"x-altinity-order": ["displayName", "description", "unit", "decimals", "color", "noValue", "hidden", "delta"]
},
"fieldConfig": {
"title": "Panel field configuration",
Expand Down Expand Up @@ -222,6 +245,16 @@
}
]
},
{
"title": "KPI",
"description": "One-row scalar and named-tuple KPI cards.",
"x-altinity-status": "implemented",
"x-altinity-snippet": { "type": "kpi" },
"properties": { "type": { "const": "kpi" } },
"required": ["type"],
"additionalProperties": true,
"x-altinity-order": ["type"]
},
{
"title": "Table",
"description": "Tabular result rendering with no required panel-specific fields.",
Expand Down Expand Up @@ -273,7 +306,7 @@
"type": {
"type": "string",
"minLength": 1,
"not": { "enum": ["bar", "hbar", "line", "area", "pie", "table", "logs", "text"] }
"not": { "enum": ["bar", "hbar", "line", "area", "pie", "kpi", "table", "logs", "text"] }
}
},
"required": ["type"],
Expand Down
Loading