Lets create frontend application for writing and testing clickhouse queries. Website will use api that can execute query and return its result (see sample code below).
For start, lest just have two large text/code fields with query text and query result. There should be one selector for clickhouse version (list of versions must be loaded when opening the page) and a button to run the query.
Base url is https://fiddle.clickhouse.com/api/
.
Here is how to get available clickhouse versions, default one should be "latest":
public getTags(): Promise<GetTagsResponse> {
return fetch(${this.apiBaseUrl}tags
)
.then((response) => response.json())
.then((response) => {
if (response.result) {
return {
tags: response.result.tags,
};
}
throw Error(response.error.message);
})
.catch((error) => {
throw error;
});
}
Here is how to make a query: public runQuery(query: string, version: string): Promise<RunQueryResponse> { const requestMetadata = { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ query, version, }), };
return fetch(`${this.apiBaseUrl}runs`, requestMetadata)
.then((response) => response.json())
.then((response) => {
if (response.result) {
return {
queryRunId: response.result.query_run_id,
output: response.result.output,
timeElapsed: response.result.time_elapsed,
};
}
throw Error(response.error.message);
})
.catch((error) => {
throw error;
});
}
I'll create a frontend application for writing and testing ClickHouse queries with the API you provided. This will include two large text/code fields for query input and results, a version selector, and a run button.
This application provides a simple interface for testing ClickHouse queries:
For a more advanced version, you could consider:
The error occurs because timeElapsed
might not be a number when you're trying to call .toFixed()
on it. Let's fix this issue by ensuring we're properly handling the type.
I've fixed the error by:
.toFixed()
to ensure we only call this method when timeElapsed
is actually a number.handleRunQuery
function to properly parse timeElapsed
as a number, handling cases where the API might return it as a string.These changes will prevent the "timeElapsed.toFixed is not a function" error by ensuring we only call .toFixed()
when timeElapsed
is definitely a number, and by attempting to convert string values to numbers when setting the state.
The application should now display the execution time correctly without throwing errors.
Task: Update the ClickHouse Playground UI to: 1. Dark‑theme support • Toggle CodeMirror’s theme and switch CSS variables on theme change. 2. Responsive design • Refactor layout using Material‑UI Grid/Box breakpoints so it adapts cleanly on mobile. 3. Fix duplicate “latest” versions • Filter out duplicate “latest” tags before rendering the version dropdown. 4. Output‑format selector (per commit 6f3f06dedbd5b8a74277e6b7e408d6b7c97fc543): • Add selectedFormat to App state, initialized from localStorage.getItem(localStorageFormatKey) || 'TabSeparated'  • Implement handleSelectedFormatChange to persist new format to localStorage and update state  • Disable the selector for server versions < 21 via a new isFormatSelectionDisabled() helper  • Pass selectedFormat into this.client.runQuery(input, selectedVersion, selectedFormat)  • In src/api/PlaygroundAPI.tsx, change the client’s runQuery signature to (query: string, version: string, format: string) and include in the POST body:
JSON.stringify({ query, version, settings: { clickhouse: { output_format: format } } })
5. Shareable query links
• On mount, parse /:id from window.location.pathname; if present, call getQueryRun(id) in PlaygroundAPI.tsx to restore a past query’s input/output.
6. VS Code–style editor
• Swap in Monaco (used by VS Code) for editing to leverage its built‑in SQL syntax highlighting.