From 590b619f02fd29745f8d90cd0bc1a12cd49f6c2e Mon Sep 17 00:00:00 2001 From: Mike Bostock Date: Fri, 8 Mar 2024 09:17:18 -0800 Subject: [PATCH 1/3] non-streaming DuckDBClient.query --- src/client/stdlib/duckdb.js | 66 ++++++++----------------------------- 1 file changed, 13 insertions(+), 53 deletions(-) diff --git a/src/client/stdlib/duckdb.js b/src/client/stdlib/duckdb.js index 12288580d..6f14b3487 100644 --- a/src/client/stdlib/duckdb.js +++ b/src/client/stdlib/duckdb.js @@ -91,7 +91,7 @@ export class DuckDBClient { throw error; } return { - schema: getArrowTableSchema(batch.value), + schema: batch.value.schema, async *readRows() { try { while (!batch.done) { @@ -106,15 +106,20 @@ export class DuckDBClient { } async query(query, params) { - const result = await this.queryStream(query, params); - const results = []; - for await (const rows of result.readRows()) { - for (const row of rows) { - results.push(row); + const connection = await this._db.connect(); + let table; + try { + if (params?.length > 0) { + const statement = await connection.prepare(query); + table = await statement.query(...params); + } else { + table = await connection.query(query); } + } catch (error) { + await connection.close(); + throw error; } - results.schema = result.schema; - return results; + return table; } async queryRow(query, params) { @@ -361,48 +366,3 @@ function isArrowTable(value) { Array.isArray(value.schema.fields) ); } - -function getArrowTableSchema(table) { - return table.schema.fields.map(getArrowFieldSchema); -} - -function getArrowFieldSchema(field) { - return { - name: field.name, - type: getArrowType(field.type), - nullable: field.nullable, - databaseType: `${field.type}` - }; -} - -// https://github.com/apache/arrow/blob/89f9a0948961f6e94f1ef5e4f310b707d22a3c11/js/src/enum.ts#L140-L141 -function getArrowType(type) { - switch (type.typeId) { - case 2: // Int - return "integer"; - case 3: // Float - case 7: // Decimal - return "number"; - case 4: // Binary - case 15: // FixedSizeBinary - return "buffer"; - case 5: // Utf8 - return "string"; - case 6: // Bool - return "boolean"; - case 8: // Date - case 9: // Time - case 10: // Timestamp - return "date"; - case 12: // List - case 16: // FixedSizeList - return "array"; - case 13: // Struct - case 14: // Union - return "object"; - case 11: // Interval - case 17: // Map - default: - return "other"; - } -} From b7265a3a6c1b954e0e63bb7e8231af3fcb4ce55f Mon Sep 17 00:00:00 2001 From: Mike Bostock Date: Fri, 8 Mar 2024 09:23:54 -0800 Subject: [PATCH 2/3] docs --- docs/sql.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/sql.md b/docs/sql.md index baa31bb41..5d74f5789 100644 --- a/docs/sql.md +++ b/docs/sql.md @@ -44,7 +44,7 @@ SELECT * FROM gaia ORDER BY phot_g_mean_mag LIMIT 10 SELECT * FROM gaia ORDER BY phot_g_mean_mag LIMIT 10 ``` -This returns an array of 10 rows, inspected here: +This returns an array of 10 rows as an [Apache Arrow](./lib/arrow) table, inspected here: ```js echo top10 From cdd2a1088ce254e9fcd6fea024f053544f1d50ad Mon Sep 17 00:00:00 2001 From: Mike Bostock Date: Fri, 8 Mar 2024 09:40:25 -0800 Subject: [PATCH 3/3] destructure instead of index --- docs/sql.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/sql.md b/docs/sql.md index 5d74f5789..421a4e22d 100644 --- a/docs/sql.md +++ b/docs/sql.md @@ -144,11 +144,11 @@ Plot.plot({ SQL fenced code blocks are shorthand for the `sql` tagged template literal. You can invoke the `sql` tagged template literal directly like so: ```js echo -const rows = await sql`SELECT random() AS random`; +const [row] = await sql`SELECT random() AS random`; ``` ```js echo -rows[0].random +row.random ``` The `sql` tag is useful for querying data within JavaScript, such as to query data for visualization without needing to create a separate SQL code block and giving the data a name. For example, below we use DuckDB to bin stars by brightness, and then visualize the bins as a histogram using a [rect mark](https://observablehq.com/plot/marks/rect).