From 09d77da786b245412dfe8806799e31f8f8bc26d6 Mon Sep 17 00:00:00 2001 From: Kevin Longe <273747162+kvlonge@users.noreply.github.com> Date: Sat, 7 Nov 2026 09:24:57 +0000 Subject: [PATCH] playground: say when the in-browser DuckDB, not the translation, failed The preview build of DuckDB-WASM the playground runs cannot bind or crashes on some translated statements that native DuckDB 2.0 runs, such as a DATEADD over CURRENT_DATE. The Run stage showed those as a red failure, which reads as a wrong translation. When the translated statement itself fails with an error from the engine (a binder, catalog, parser, not-implemented or internal error, or a WebAssembly crash), the Run stage now says it is a limit of the in-browser DuckDB, not of the translation, that SQLQuack translates for native DuckDB 2.0, and shows DuckDB-WASM's error underneath. Errors about values, errors from the fixture rows and errors Snowflake would raise keep their existing messages. --- website/public/playground/playground.js | 19 ++++++++++++++++++- website/public/playground/spans.js | 7 +++++++ website/tests/playground.test.mjs | 11 ++++++++++- 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/website/public/playground/playground.js b/website/public/playground/playground.js index 1bd592748..a6b9923e2 100644 --- a/website/public/playground/playground.js +++ b/website/public/playground/playground.js @@ -5,7 +5,7 @@ import { DUCKDB_DIR, DUCKDB_WASM_BYTES } from './duckdb-version.js'; import { ENGINE_DIR, ENGINE_WASM_BYTES } from './engine-version.js'; import { CAPTIONS, EXAMPLE_GROUPS, EXAMPLES, ROWS, SCHEMA, stopLabel } from './examples.js'; -import { escape, rendered, resultTable, underlined } from './spans.js'; +import { escape, previewLimit, rendered, resultTable, underlined } from './spans.js'; const here = (path) => new URL(path, import.meta.url).href; const ENGINE_WASM = here(`${ENGINE_DIR}sqlquack_wasm_bg.wasm`); @@ -362,6 +362,8 @@ async function execute() { if (!sql) return; const ticket = ++running; setStage('run', 'running', ''); + // Whether the error came from the translated statement itself, after the fixture loaded. + let ranStatement = false; try { if (!duckdb) await startDuckDB(); const conn = await duckdb.db.connect(); @@ -371,6 +373,7 @@ async function execute() { for (const table of tables.tables) await conn.query(table.replace(/^CREATE TABLE/, 'CREATE OR REPLACE TABLE')); if (rowsBox.value.trim()) await conn.query(rowsBox.value); const started = performance.now(); + ranStatement = true; // Every value as DuckDB's own text, so decimals and timestamps show exactly. const result = await conn.query(`SELECT COLUMNS(*)::VARCHAR FROM (${sql}) AS result`); const elapsed = performance.now() - started; @@ -392,6 +395,20 @@ async function execute() { const failure = JSON.parse((await engine('failure', { message })).result); if (ticket !== running) return; const version = duckdb ? `DuckDB ${duckdb.version}` : ''; + if (!failure.errno && ranStatement && previewLimit(message)) { + setStage( + 'run', + 'refused', + '
A limit of the in-browser DuckDB, not of the translation. ' +
+ 'This page runs a preview build of DuckDB-WASM, which could not run this translated SQL. SQLQuack translates for ' +
+ 'native DuckDB 2.0: sqlquack convert binds every translated statement in native DuckDB before ' +
+ 'returning it, so run it there to see the result.