From 7c69b22f8b355ac8a38e6db362f91102954f5d6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Rivi=C3=A8re?= Date: Tue, 19 Mar 2024 00:43:43 +0100 Subject: [PATCH] DuckDBClient.sql (#1097) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * implement sql fenced code from DuckDBClient.sql(…) following @mbostock’s suggestion https://github.com/observablehq/framework/issues/1072#issuecomment-2000253228 * fix typo --------- Co-authored-by: Mike Bostock --- docs/lib/duckdb.md | 16 +++++++++++++++- docs/sql.md | 4 +++- src/client/stdlib/duckdb.js | 4 ++++ 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/docs/lib/duckdb.md b/docs/lib/duckdb.md index d8b2fbddd..e9137b319 100644 --- a/docs/lib/duckdb.md +++ b/docs/lib/duckdb.md @@ -90,4 +90,18 @@ And `db.queryRow`: db.queryRow("SELECT count() AS count FROM gaia") ``` -See the [DatabaseClient Specification](https://observablehq.com/@observablehq/database-client-specification) for more details. +See the [DatabaseClient Specification](https://observablehq.com/@observablehq/database-client-specification) for more details on these methods. + +Finally, the `DuckDBClient.sql` method takes the same arguments as `DuckDBClient.of` and returns the corresponding `db.sql` tagged template literal. The returned function can be used to redefine the built-in [`sql` tagged template literal](../sql#sql-literals) and thereby change the database used by [SQL code blocks](../sql), allowing you to query dynamically-registered tables (unlike the **sql** front matter option). + +```js +const feed = view(Inputs.select(new Map([["M4.5+", "4.5"], ["M2.5+", "2.5"], ["All", "all"]]), {label: "Earthquake feed"})); +``` + +```js echo +const sql = DuckDBClient.sql({quakes: `https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/${feed}_day.csv`}); +``` + +```sql echo +SELECT * FROM quakes ORDER BY updated DESC; +``` diff --git a/docs/sql.md b/docs/sql.md index e87d1f26d..0b862ad31 100644 --- a/docs/sql.md +++ b/docs/sql.md @@ -27,6 +27,8 @@ sql:
For performance and reliability, we recommend using local files rather than loading data from external servers at runtime. If needed, you can use a data loader to take a snapshot of a remote data during build.
+You can also register tables via code (say to have sources that are defined dynamically via user input) by defining the `sql` symbol with [DuckDBClient.sql](./lib/duckdb). + ## SQL code blocks To run SQL queries, create a SQL fenced code block (```sql). For example, to query the first 10 rows from the `gaia` table: @@ -182,6 +184,6 @@ Plot.plot({ The `sql` tag is available by default in Markdown. You can also import it explicitly as: -```js echo +```js run=false import {sql} from "npm:@observablehq/duckdb"; ``` diff --git a/src/client/stdlib/duckdb.js b/src/client/stdlib/duckdb.js index 711bdb301..2ab8c8667 100644 --- a/src/client/stdlib/duckdb.js +++ b/src/client/stdlib/duckdb.js @@ -173,6 +173,10 @@ export class DuckDBClient { await Promise.all(Object.entries(sources).map(([name, source]) => insertSource(db, name, source))); return new DuckDBClient(db); } + + static sql() { + return this.of.apply(this, arguments).then((db) => db.sql.bind(db)); + } } Object.defineProperty(DuckDBClient.prototype, "dialect", {