Skip to content

Commit 01addc7

Browse files
authored
non-streaming DuckDBClient.query (#1024)
* non-streaming DuckDBClient.query * docs
1 parent cdd6c35 commit 01addc7

File tree

2 files changed

+16
-56
lines changed

2 files changed

+16
-56
lines changed

docs/sql.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ SELECT * FROM gaia ORDER BY phot_g_mean_mag LIMIT 10
4444
SELECT * FROM gaia ORDER BY phot_g_mean_mag LIMIT 10
4545
```
4646

47-
This returns an array of 10 rows, inspected here:
47+
This returns an array of 10 rows as an [Apache Arrow](./lib/arrow) table, inspected here:
4848

4949
```js echo
5050
top10
@@ -144,11 +144,11 @@ Plot.plot({
144144
SQL fenced code blocks are shorthand for the `sql` tagged template literal. You can invoke the `sql` tagged template literal directly like so:
145145

146146
```js echo
147-
const rows = await sql`SELECT random() AS random`;
147+
const [row] = await sql`SELECT random() AS random`;
148148
```
149149

150150
```js echo
151-
rows[0].random
151+
row.random
152152
```
153153

154154
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).

src/client/stdlib/duckdb.js

+13-53
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ export class DuckDBClient {
9191
throw error;
9292
}
9393
return {
94-
schema: getArrowTableSchema(batch.value),
94+
schema: batch.value.schema,
9595
async *readRows() {
9696
try {
9797
while (!batch.done) {
@@ -106,15 +106,20 @@ export class DuckDBClient {
106106
}
107107

108108
async query(query, params) {
109-
const result = await this.queryStream(query, params);
110-
const results = [];
111-
for await (const rows of result.readRows()) {
112-
for (const row of rows) {
113-
results.push(row);
109+
const connection = await this._db.connect();
110+
let table;
111+
try {
112+
if (params?.length > 0) {
113+
const statement = await connection.prepare(query);
114+
table = await statement.query(...params);
115+
} else {
116+
table = await connection.query(query);
114117
}
118+
} catch (error) {
119+
await connection.close();
120+
throw error;
115121
}
116-
results.schema = result.schema;
117-
return results;
122+
return table;
118123
}
119124

120125
async queryRow(query, params) {
@@ -361,48 +366,3 @@ function isArrowTable(value) {
361366
Array.isArray(value.schema.fields)
362367
);
363368
}
364-
365-
function getArrowTableSchema(table) {
366-
return table.schema.fields.map(getArrowFieldSchema);
367-
}
368-
369-
function getArrowFieldSchema(field) {
370-
return {
371-
name: field.name,
372-
type: getArrowType(field.type),
373-
nullable: field.nullable,
374-
databaseType: `${field.type}`
375-
};
376-
}
377-
378-
// https://github.com/apache/arrow/blob/89f9a0948961f6e94f1ef5e4f310b707d22a3c11/js/src/enum.ts#L140-L141
379-
function getArrowType(type) {
380-
switch (type.typeId) {
381-
case 2: // Int
382-
return "integer";
383-
case 3: // Float
384-
case 7: // Decimal
385-
return "number";
386-
case 4: // Binary
387-
case 15: // FixedSizeBinary
388-
return "buffer";
389-
case 5: // Utf8
390-
return "string";
391-
case 6: // Bool
392-
return "boolean";
393-
case 8: // Date
394-
case 9: // Time
395-
case 10: // Timestamp
396-
return "date";
397-
case 12: // List
398-
case 16: // FixedSizeList
399-
return "array";
400-
case 13: // Struct
401-
case 14: // Union
402-
return "object";
403-
case 11: // Interval
404-
case 17: // Map
405-
default:
406-
return "other";
407-
}
408-
}

0 commit comments

Comments
 (0)