docs: fill in several undocumented Cube Cloud features - #11552
Conversation
feat(cubesql) #11503 added regtype/regtype[] cast resolution for OID columns like pg_attribute.atttypid, used by BI tools' schema-introspection queries over the Postgres wire protocol. No docs update shipped with it. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012YfuZsgFKyGSnKf9iSQs6V
|
Preview deployment for your docs. Learn more about Mintlify Previews.
💡 Tip: Enable Workflows to automatically generate PRs for you. |
|
Claude finished @keydunov's task in 1m 59s —— View job Review: 1 accuracy issue, 2 structural nits — docs-only, no code riskFull review (click to expand)
SummaryGood catch on the docs gap — #11503 shipped a customer-facing behavior with no reference entry, and this is exactly the right page for it. The section follows the page's One factual problem, verified against the implementation. Accuracy: the description is inverted for
|
| Form | Operand | Rewritten to | Direction |
|---|---|---|---|
::regtype |
column identifier | format_type(col, NULL) — statement.rs:1230-1240 |
OID → type name |
::regtype[] |
string array literal | ARRAY[20, 1700, 16] — replace_regtype_array_cast, statement.rs:1016 |
type names → OIDs |
There is no code path that turns an OID column into an array of type names, so "Resolves an OID column … to a Postgres type name" is wrong for ::regtype[]. The Domo query the feature was built for (domo_column_inspection_query.snap) shows the real shape:
a.atttypid = ANY ('{int8,numeric,bool}'::regtype[])Suggested split into two rows is in the inline comment.
Structural nits (low)
- Missing
Pushdown/Post-processingcolumns. Every other table in the "SQL functions and operators" section has them; only the trailing "Custom functions" table doesn't. Omission here is defensible (these casts arepg_catalogintrospection, never pushed down) but should be said, not implied. - Placement. Lines 195–361 mirror the Postgres functions docs; a cast-syntax section linking to
sql-expressions.htmlinterrupts that run. Just before "Custom functions" (line 527) is a better fit. — inline comment
Optional follow-up (out of scope for this PR)
The to_regtype() UDF (common.rs:3793) and format_type() are also registered and undocumented on this page. Since the corrected ::regtype description effectively describes format_type, adding them could be a natural companion — but it predates this PR and isn't required here.
Focus areas not applicable
Security, performance, and error handling: this is a docs-only change (+14/-0 in one .mdx), no runtime surface. Testing: no tests apply; the underlying behavior is covered by the introspection snapshots listed above.
|
|
||
| | Cast | Description | | ||
| | --- | --- | | ||
| | `::regtype`, `::regtype[]` | Resolves an OID column (e.g., `pg_attribute.atttypid`) to a Postgres type name. Used by BI tools that inspect table columns over the Postgres wire protocol. | |
There was a problem hiding this comment.
The description is accurate for ::regtype but inverted for ::regtype[]. The two casts do opposite things in the implementation:
::regtypeon a column identifier is rewritten toformat_type(col, NULL)→ yields a type name (statement.rs:1230-1240). This matches the row's wording.::regtype[]is only handled on a string literal array —'{int8,numeric,bool}'::regtype[]is expanded toARRAY[20, 1700, 16], i.e. it resolves type names to OIDs (replace_regtype_array_cast,statement.rs:1016). There is no path that turns an OID column into an array of type names.
A reader following this row would write a.atttypid::regtype[] and get nothing useful. Splitting into two rows also lets you state the operand shape each form accepts (a bare column identifier vs. a string literal) — casts of arbitrary expressions fall through untouched (statement.rs:1259).
| | `::regtype`, `::regtype[]` | Resolves an OID column (e.g., `pg_attribute.atttypid`) to a Postgres type name. Used by BI tools that inspect table columns over the Postgres wire protocol. | | |
| | `::regtype` | Resolves an OID column (e.g., `pg_attribute.atttypid`) to a Postgres type name | | |
| | `::regtype[]` | Resolves an array literal of type names (e.g., `'{int8,numeric,bool}'::regtype[]`) to the corresponding OIDs, so it can be compared against an OID column | |
Worth adding a one-line example below the table, since the shape BI tools emit isn't obvious from the description alone:
SELECT a.attname, format_type(a.atttypid, NULL) AS data_type
FROM pg_catalog.pg_attribute a
WHERE a.atttypid = ANY ('{int8,numeric,bool}'::regtype[]);| ### Type casts | ||
|
|
||
| <Info> | ||
|
|
||
| Learn more in the | ||
| [relevant section](https://www.postgresql.org/docs/current/sql-expressions.html#SQL-SYNTAX-TYPE-CASTS) | ||
| of the PostgreSQL documentation. | ||
|
|
||
| </Info> | ||
|
|
||
| | Cast | Description | | ||
| | --- | --- | |
There was a problem hiding this comment.
Two structural notes on the new section:
1. The table drops the Pushdown / Post-processing columns that every other table under "SQL functions and operators" carries (only the trailing "Custom functions" table omits them). Silently dropping them reads as an oversight rather than as "not applicable." Since regtype casts are a pg_catalog introspection concern and never reach a data source, one short sentence above the table would resolve it — e.g. "These casts are resolved by the SQL API in introspection queries against pg_catalog; they are not pushed down to the data source."
2. Placement. Sections 195–361 all mirror the Postgres functions docs and are roughly in that doc's order; this one links to sql-expressions.html and describes syntax, not a function or operator. Inserting it between "Data type formatting functions" and "Date/time functions" breaks that run. Moving it just before "Custom functions" (line 527) — where the 2-column table shape already has precedent — would fit better.
Fills in customer-facing changes that shipped in cubejs-enterprise without an accompanying docs update, found via a sweep of recent commits against docs-mintlify: - Dashboard controls: cross-view mapping suggestion banner - Pie/donut chart: grouping small slices into an "Other" bucket - Chart type picker: searching for unsupported chart concepts, and the unmet-requirement tooltip on disabled entries - Small multiples: splitting by a second dimension (was previously documented as unsupported) - Chart widgets: per-widget CSV/PNG/PDF download - MCP server: deploymentId is accepted by every tool, not just chat - Snowflake Semantic Views: scoping a pull to named views - AI Tokens: embedded users' token spend billed outside seat coverage Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012YfuZsgFKyGSnKf9iSQs6V
|
Claude finished @keydunov's task in 2m 45s —— View job Review of
|
| # | Severity | File | Issue |
|---|---|---|---|
| 1 | High | dashboards/widgets/charts.mdx:34 |
"Requires the Download data permission" contradicts the section it links to — dashboards/index.mdx:83 gates PNG/PDF on Manage on the owning workbook, and custom-roles.mdx:122 scopes Download data to CSV. (inline) |
| 2 | Medium | charts/configuration/small-multiples.mdx:24 |
"instead of a single row of panels" — single-dimension splits are already a grid per line 32 ("a four-value dimension opens as a 2 × 2 grid"). Also, Grid and How many panels are drawn are still written for one dimension now that the limitation bullet is gone. (inline) |
| 3 | Medium | admin/account-billing/ai-tokens.mdx:71-77 |
Embedded billing applies both the contract path (token packages) and the on-demand path to the same usage, cutting across the page's own customer-type split; "Free plan accounts … have no seats" conflicts with the Free tier section below; and it's unclear whether the embedded spend limit is separate from the account-wide one. Plus /embedding is the first bare link to that index page — worth clicking on the preview. (inline) |
| 4 | Low | docs/integrations/mcp-server.mdx:209-211 |
Says the same thing as the line-190 addition, and its validation clause duplicates the existing paragraph at 231–234. Also flags "every tool accepts deploymentId" as a strong universal worth confirming — loadQueryResults reads like an exception. (inline) |
Verified clean
[ref-dashboard-download]: /docs/explore-analyze/dashboards#download-as-png-or-pdfresolves — heading exists atdashboards/index.mdx:69, andnotifications.mdx:55already uses the identical URL.- Naming conventions per
docs-mintlify/CLAUDE.md: no "Cube Cloud" in the added prose, no H1s, root-relative links throughout, plan-tier phrasing not invoked. pie.mdx"Grouping small slices" andcontrols.mdx"Mapping suggestions across views" read cleanly and sit in the right sections — no structural issues found.chart-types/index.mdxis the densest addition (a seven-item quoted list inside one paragraph). Not wrong, and the section earns its place, but it's the one spot where a short bullet list would scan better than prose.
Prior threads re-affirmed, not re-posted
Commit 11559ec (regtype) is untouched by this push, so both earlier threads still stand and I did not duplicate them:
reference.mdx:375—::regtype[]description is inverted (it resolves type names → OIDs, not the reverse).reference.mdx:374— missingPushdown/Post-processingcolumns; placement.
Focus areas not applicable
Security, performance, error handling, test coverage: docs-only change, no runtime surface and no test hooks.
|
|
||
| Open a chart widget's `⋮` menu on a published dashboard and choose **Download as CSV**, | ||
| **Download as PNG**, or **Download as PDF** to export just that chart, without downloading | ||
| the whole dashboard. Requires the **Download data** permission. See [Download as PNG or |
There was a problem hiding this comment.
The permission claim conflicts with the whole-dashboard section it links to.
docs/explore-analyze/dashboards/index.mdx:83 gates dashboard-level PNG/PDF on a different permission entirely:
Available to users with Manage permission on the workbook that owns the dashboard.
And Download data is described in admin/users-and-permissions/custom-roles.mdx:122 as CSV-scoped:
Download query results as CSV from workbooks, Analytics Chat, and published dashboards.
So one blanket "Requires the Download data permission" across all three formats is very likely wrong for at least PNG/PDF — either they follow the dashboard rule (Manage on the owning workbook), or per-widget image export deliberately diverges from whole-dashboard export, which is surprising enough to state explicitly. A reader with Download data but not Manage can't tell from this page which of the three menu items they'll actually see.
Please confirm against the implementation and split if the gates differ, e.g.:
| the whole dashboard. Requires the **Download data** permission. See [Download as PNG or | |
| the whole dashboard. **Download as CSV** requires the **Download data** permission; | |
| **Download as PNG** and **Download as PDF** require **Manage** permission on the workbook | |
| that owns the dashboard. See [Download as PNG or | |
| PDF][ref-dashboard-download] for the whole-dashboard equivalent. |
Minor, same paragraph: the dashboard page spells this affordance More actions (⋯); using a bare ⋮ here is a second name for the same kind of menu.
| ### Splitting by a second dimension | ||
|
|
||
| Once **Split by** is set, a **Second dimension** picker appears. Pick a dimension there to | ||
| lay panels out on a 2-D grid — the first dimension's values run down the rows and the | ||
| second dimension's values run across the columns, instead of a single row of panels. |
There was a problem hiding this comment.
"instead of a single row of panels" contradicts the rest of the page. Single-dimension splits are already laid out as a grid — line 32 says the Grid option is "Columns × rows, up to 5 × 5. Both are preselected from the number of distinct values in the split dimension, so a four-value dimension opens as a 2 × 2 grid." A reader who just read that will hit this sentence and conclude one of the two is wrong. Dropping the trailing clause fixes it; the "rows = first dimension, columns = second" sentence carries the meaning on its own.
| ### Splitting by a second dimension | |
| Once **Split by** is set, a **Second dimension** picker appears. Pick a dimension there to | |
| lay panels out on a 2-D grid — the first dimension's values run down the rows and the | |
| second dimension's values run across the columns, instead of a single row of panels. | |
| ### Splitting by a second dimension | |
| Once **Split by** is set, a **Second dimension** picker appears. Pick a dimension there to | |
| lay panels out on a 2-D grid — the first dimension's values run down the rows and the | |
| second dimension's values run across the columns, rather than filling the grid | |
| left-to-right with a single dimension's values. |
Two follow-on sections are still written as if only one split dimension exists, and are worth a sentence each now that the limitation bullet is gone:
- Grid (line 32) — if rows/columns are now driven by the two dimensions' distinct values, is the picker still user-settable in 2-D mode, or does it become read-only? "Both are preselected from the number of distinct values in the split dimension" is singular.
- How many panels are drawn (lines 45–51) — "when a dimension has more values than the grid has tiles, the chart draws the first ones in the current sort order" and Sort panels by both assume one axis of values. With two dimensions, truncation and sorting presumably apply per axis; saying so avoids guesswork.
| ## Embedded users | ||
|
|
||
| AI token usage by [embedded][ref-embedding] end users is not drawn from the account's | ||
| per-seat token grants — it is billed separately through token packages, then as | ||
| on-demand consumption. By default there is no on-demand spending limit for embedded | ||
| usage; set one to cap it, the same way you would for on-demand consumption above. Free | ||
| plan accounts are unaffected, since they have no seats. |
There was a problem hiding this comment.
This section crosses the page's own customer-type split without acknowledging it. The Overview (lines 13–19) partitions everything into on-demand customers (per-seat grants → on-demand consumption) and contract customers (pooled token packages). This paragraph applies both paths to the same embedded usage — "billed separately through token packages, then as on-demand consumption" — which is a third billing mode. That may well be correct, but as written it reads like a contradiction. Naming the order explicitly would fix it: packages are drawn down first if the account has any, and anything beyond that (or all of it, for an account with no packages) falls to on-demand.
Two smaller points in the same block:
- "Free plan accounts are unaffected, since they have no seats" — the Free tier section immediately below says "each user on a free plan receives an individual monthly token allowance," so "no seats" is doing subtle work a reader won't follow. If the real statement is that free accounts can't have embedded users at all, say that; if it's that embedded usage on a free plan draws from the free allowance, say that instead.
- "By default there is no on-demand spending limit for embedded usage" — is this a separate limit from the account-wide "monthly on-demand spending limit" at line 56, or does the same setting cover embedded once you set it? "set one … the same way you would for on-demand consumption above" is ambiguous between the two, and the answer decides whether an admin who already set an account limit is protected.
Also, [ref-embedding]: /embedding (line 131) is the first bare /embedding link in the docs — every other reference goes to a sub-path (/embedding/iframe/...). docs.json:427 registers that page as "embedding/index", not as a group root: the way docs/explore-analyze/dashboards/index is (docs.json:108), so it's worth clicking through on the Mintlify preview to confirm /embedding resolves rather than 404s.
| Every other tool below — query, discovery, dashboard authoring, data model editing, and | ||
| pre-aggregations — also accepts an optional `deploymentId` to target a deployment other | ||
| than the session default. |
There was a problem hiding this comment.
This paragraph restates what line 190 (also added in this commit) already says — "every tool accepts an optional deploymentId" — and the validation half of line 191 duplicates the existing paragraph at lines 231–234 ("Requests are always validated against the admin's deployment-access settings…"). docs-mintlify/CLAUDE.md asks for "say it once."
The listing of tool groups here is the part that's actually new information, so I'd keep this paragraph and trim the additions to line 190 back to the original sentence:
| Every other tool below — query, discovery, dashboard authoring, data model editing, and | |
| pre-aggregations — also accepts an optional `deploymentId` to target a deployment other | |
| than the session default. | |
| Every other tool below — query, discovery, dashboard authoring, data model editing, and | |
| pre-aggregations — also accepts an optional `deploymentId` to target a deployment other | |
| than the session default. |
(and revert lines 189–191 to …and target a specific one on each request.)
One accuracy check while you're here: "every tool accepts an optional deploymentId" is a strong universal over 20 tools. loadQueryResults is described two lines up as operating "on the same deployment context," which reads like it does not take one. Worth confirming the claim holds for all 20 — if there are exceptions, "most tools" plus the exception list is safer than a blanket "every."
Check List
Description of Changes Made
Found via a routine sweep of recent commits in
cube-js/cubeandcubedevinc/cubejs-enterprisecross-checked against docs-mintlify for undocumented customer-facing changes.::regtype/::regtype[]cast support (feat(cubesql): Supportregtypeandregtype[]casts #11503 shipped without docs)controls.mdx)pie.mdx)chart-types/index.mdx)small-multiples.mdx)widgets/charts.mdx)deploymentIdis accepted by every tool, not justchat(mcp-server.mdx)snowflake-semantic-views.mdx)ai-tokens.mdx)Excluded from this pass (flag-gated / not yet on by default, or already documented elsewhere): the Dashboard Apps component library, the Board dashboard-editor engine, AI token allowance on the Billing page, and the centralized MCP endpoint rollout. A larger rework — the "AI Summary" widget being renamed to "Analysis" with new refresh UI — is tracked separately as a Linear ticket since it needs a near-full rewrite of its docs page rather than a section add.