Skip to content

Commit 3a3ca5e

Browse files
authored
Merge pull request #3062 from perspective-dev/duckdb
DuckDB Virtual Server
2 parents 079537d + 87bf5aa commit 3a3ca5e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

72 files changed

+5160
-181
lines changed

.github/workflows/build.yaml

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ jobs:
7373
- ubuntu-22.04
7474
python-version:
7575
- 3.9
76-
node-version: [20.x]
76+
node-version: [22.x]
7777

7878
steps:
7979
- name: Checkout
@@ -125,7 +125,7 @@ jobs:
125125
- ubuntu-22.04
126126
python-version:
127127
- 3.9
128-
node-version: [20.x]
128+
node-version: [22.x]
129129

130130
steps:
131131
- name: Checkout
@@ -193,7 +193,7 @@ jobs:
193193
- x86_64
194194
python-version:
195195
- 3.9
196-
node-version: [20.x]
196+
node-version: [22.x]
197197
include:
198198
- os: ubuntu-22.04
199199
arch: x86_64
@@ -305,7 +305,7 @@ jobs:
305305
- windows-2022
306306
arch:
307307
- x86_64
308-
node-version: [20.x]
308+
node-version: [22.x]
309309
is-release:
310310
- ${{ startsWith(github.ref, 'refs/tags/v') || github.ref_name == 'master' }}
311311
exclude:
@@ -395,7 +395,7 @@ jobs:
395395
- x86_64
396396
python-version:
397397
- 3.9
398-
node-version: [20.x]
398+
node-version: [22.x]
399399
steps:
400400
- name: Checkout
401401
uses: actions/checkout@v4
@@ -443,7 +443,7 @@ jobs:
443443
- x86_64
444444
python-version:
445445
- 3.9
446-
node-version: [20.x]
446+
node-version: [22.x]
447447
steps:
448448
- name: Checkout
449449
uses: actions/checkout@v4
@@ -510,7 +510,7 @@ jobs:
510510
- x86_64
511511
python-version:
512512
- 3.9
513-
node-version: [20.x]
513+
node-version: [22.x]
514514
is-release:
515515
- ${{ startsWith(github.ref, 'refs/tags/v') || github.ref_name == 'master' }}
516516
exclude:
@@ -621,7 +621,7 @@ jobs:
621621
- ubuntu-22.04
622622
python-version:
623623
- 3.9
624-
node-version: [20.x]
624+
node-version: [22.x]
625625

626626
steps:
627627
- name: Checkout
@@ -674,7 +674,7 @@ jobs:
674674
python-version:
675675
- 3.9
676676
# - 3.12
677-
node-version: [20.x]
677+
node-version: [22.x]
678678
is-release:
679679
- ${{ startsWith(github.ref, 'refs/tags/v') || github.ref_name == 'master' }}
680680
exclude:
@@ -823,7 +823,7 @@ jobs:
823823
matrix:
824824
os: [ubuntu-22.04]
825825
python-version: [3.9]
826-
node-version: [20.x]
826+
node-version: [22.x]
827827
arch: [x86_64]
828828
steps:
829829
- name: Checkout
@@ -880,7 +880,7 @@ jobs:
880880
strategy:
881881
matrix:
882882
os: [ubuntu-22.04]
883-
node-version: [20.x]
883+
node-version: [22.x]
884884
runs-on: ${{ matrix.os }}
885885
steps:
886886
- name: Checkout

Cargo.lock

Lines changed: 27 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README.md

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
<br />
2+
23
<a href="https://perspective-dev.github.io">
34
<picture>
45
<source media="(prefers-color-scheme: dark)" srcset="https://github.com/perspective-dev/perspective/raw/master/docs/static/svg/perspective-logo-dark.svg?raw=true">
@@ -14,27 +15,33 @@
1415

1516
<br/>
1617

17-
Perspective is an <i>interactive</i> analytics and data visualization component,
18-
which is especially well-suited for <i>large</i> and/or <i>streaming</i>
19-
datasets. Use it to create user-configurable reports, dashboards, notebooks and
20-
applications.
18+
Perspective is an interactive analytics and data visualization component for
19+
large and streaming datasets. Build user-configurable reports, dashboards,
20+
notebooks, and applications with a high-performance query engine compiled to
21+
WebAssembly, Python, and Rust.
2122

2223
### Features
2324

24-
- A fast, memory efficient streaming query engine, written in C++ and compiled
25-
for [WebAssembly](https://webassembly.org/), [Python](https://www.python.org/)
26-
and [Rust](https://www.rust-lang.org/), with read/write/streaming for
27-
[Apache Arrow](https://arrow.apache.org/), and a high-performance columnar
28-
expression language based on [ExprTK](https://github.com/ArashPartow/exprtk).
29-
30-
- A framework-agnostic User Interface packaged as a
25+
- A framework-agnostic user interface packaged as a
3126
[Custom Element](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements),
32-
powered either in-browser via WebAssembly or virtually via WebSocket server
33-
(Python/Node/Rust).
27+
which connects to a Data Model in-browser (via WebAssembly) or remotely (via
28+
WebSocket, with integration in Python, Node.js and Rust). Includes a data
29+
grid, 10+ chart types line, bar, area, scatter, heatmap, treemap, sunburst,
30+
candlestick, and more.
31+
32+
- A Data Model API for pluggable engines, enabling Perspective's UI to query
33+
external data sources like [DuckDB](https://duckdb.org/) while translating
34+
view configurations into native queries.
35+
36+
- A fast, memory-efficient streaming Data Model built-in, written in C++ and
37+
compiled for [WebAssembly](https://webassembly.org/),
38+
[Python](https://www.python.org/), and [Rust](https://www.rust-lang.org/).
39+
Supports read/write/streaming for [Apache Arrow](https://arrow.apache.org/),
40+
with a columnar expression language based on
41+
[ExprTK](https://github.com/ArashPartow/exprtk).
3442

35-
- A [JupyterLab](https://jupyter.org/) widget and Python client library, for
36-
interactive data analysis in a notebook, as well as _scalable_ production
37-
applications.
43+
- A [JupyterLab](https://jupyter.org/) widget and Python client library for
44+
interactive data analysis in notebooks.
3845

3946
### Documentation
4047

@@ -62,7 +69,7 @@ applications.
6269
### Examples
6370

6471
<!-- Examples -->
65-
<table><tbody><tr><td>editable</td><td>file</td><td>fractal</td></tr><tr><td><a href="https://perspective-dev.github.io/block?example=editable"><img height="125" src="https://perspective-dev.github.io/blocks/editable/preview.png?"></img></a></td><td><a href="https://perspective-dev.github.io/block?example=file"><img height="125" src="https://perspective-dev.github.io/blocks/file/preview.png?"></img></a></td><td><a href="https://perspective-dev.github.io/block?example=fractal"><img height="125" src="https://perspective-dev.github.io/blocks/fractal/preview.png?"></img></a></td></tr><tr><td>market</td><td>raycasting</td><td>evictions</td></tr><tr><td><a href="https://perspective-dev.github.io/block?example=market"><img height="125" src="https://perspective-dev.github.io/blocks/market/preview.png?"></img></a></td><td><a href="https://perspective-dev.github.io/block?example=raycasting"><img height="125" src="https://perspective-dev.github.io/blocks/raycasting/preview.png?"></img></a></td><td><a href="https://perspective-dev.github.io/block?example=evictions"><img height="125" src="https://perspective-dev.github.io/blocks/evictions/preview.png?"></img></a></td></tr><tr><td>nypd</td><td>streaming</td><td>covid</td></tr><tr><td><a href="https://perspective-dev.github.io/block?example=nypd"><img height="125" src="https://perspective-dev.github.io/blocks/nypd/preview.png?"></img></a></td><td><a href="https://perspective-dev.github.io/block?example=streaming"><img height="125" src="https://perspective-dev.github.io/blocks/streaming/preview.png?"></img></a></td><td><a href="https://perspective-dev.github.io/block?example=covid"><img height="125" src="https://perspective-dev.github.io/blocks/covid/preview.png?"></img></a></td></tr><tr><td>webcam</td><td>movies</td><td>superstore</td></tr><tr><td><a href="https://perspective-dev.github.io/block?example=webcam"><img height="125" src="https://perspective-dev.github.io/blocks/webcam/preview.png?"></img></a></td><td><a href="https://perspective-dev.github.io/block?example=movies"><img height="125" src="https://perspective-dev.github.io/blocks/movies/preview.png?"></img></a></td><td><a href="https://perspective-dev.github.io/block?example=superstore"><img height="125" src="https://perspective-dev.github.io/blocks/superstore/preview.png?"></img></a></td></tr><tr><td>citibike</td><td>olympics</td><td>dataset</td></tr><tr><td><a href="https://perspective-dev.github.io/block?example=citibike"><img height="125" src="https://perspective-dev.github.io/blocks/citibike/preview.png?"></img></a></td><td><a href="https://perspective-dev.github.io/block?example=olympics"><img height="125" src="https://perspective-dev.github.io/blocks/olympics/preview.png?"></img></a></td><td><a href="https://perspective-dev.github.io/block?example=dataset"><img height="125" src="https://perspective-dev.github.io/blocks/dataset/preview.png?"></img></a></td></tr></tbody></table>
72+
<table><tbody><tr><td>editable</td><td>file</td><td>duckdb</td></tr><tr><td><a href="https://perspective-dev.github.io/block?example=editable"><img height="125" src="https://perspective-dev.github.io/blocks/editable/preview.png?"></img></a></td><td><a href="https://perspective-dev.github.io/block?example=file"><img height="125" src="https://perspective-dev.github.io/blocks/file/preview.png?"></img></a></td><td><a href="https://perspective-dev.github.io/block?example=duckdb"><img height="125" src="https://perspective-dev.github.io/blocks/duckdb/preview.png?"></img></a></td></tr><tr><td>fractal</td><td>market</td><td>raycasting</td></tr><tr><td><a href="https://perspective-dev.github.io/block?example=fractal"><img height="125" src="https://perspective-dev.github.io/blocks/fractal/preview.png?"></img></a></td><td><a href="https://perspective-dev.github.io/block?example=market"><img height="125" src="https://perspective-dev.github.io/blocks/market/preview.png?"></img></a></td><td><a href="https://perspective-dev.github.io/block?example=raycasting"><img height="125" src="https://perspective-dev.github.io/blocks/raycasting/preview.png?"></img></a></td></tr><tr><td>evictions</td><td>nypd</td><td>streaming</td></tr><tr><td><a href="https://perspective-dev.github.io/block?example=evictions"><img height="125" src="https://perspective-dev.github.io/blocks/evictions/preview.png?"></img></a></td><td><a href="https://perspective-dev.github.io/block?example=nypd"><img height="125" src="https://perspective-dev.github.io/blocks/nypd/preview.png?"></img></a></td><td><a href="https://perspective-dev.github.io/block?example=streaming"><img height="125" src="https://perspective-dev.github.io/blocks/streaming/preview.png?"></img></a></td></tr><tr><td>covid</td><td>webcam</td><td>movies</td></tr><tr><td><a href="https://perspective-dev.github.io/block?example=covid"><img height="125" src="https://perspective-dev.github.io/blocks/covid/preview.png?"></img></a></td><td><a href="https://perspective-dev.github.io/block?example=webcam"><img height="125" src="https://perspective-dev.github.io/blocks/webcam/preview.png?"></img></a></td><td><a href="https://perspective-dev.github.io/block?example=movies"><img height="125" src="https://perspective-dev.github.io/blocks/movies/preview.png?"></img></a></td></tr><tr><td>superstore</td><td>citibike</td><td>olympics</td></tr><tr><td><a href="https://perspective-dev.github.io/block?example=superstore"><img height="125" src="https://perspective-dev.github.io/blocks/superstore/preview.png?"></img></a></td><td><a href="https://perspective-dev.github.io/block?example=citibike"><img height="125" src="https://perspective-dev.github.io/blocks/citibike/preview.png?"></img></a></td><td><a href="https://perspective-dev.github.io/block?example=olympics"><img height="125" src="https://perspective-dev.github.io/blocks/olympics/preview.png?"></img></a></td></tr><tr><td>dataset</td></tr><tr><td><a href="https://perspective-dev.github.io/block?example=dataset"><img height="125" src="https://perspective-dev.github.io/blocks/dataset/preview.png?"></img></a></td></tr></tbody></table>
6673
<!-- Examples -->
6774

6875
### Media

examples/README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,13 @@ In order to _run_ a project in this directory as written:
1212
2. Run the project with `pnpm run start $PROJECT_NAME` from the repository root
1313
(_not_ the `/examples` directory).
1414

15+
## VirtualServer Examples
16+
17+
These examples demonstrate custom data source implementations using the VirtualServer API, which allows you to create backends that serve data from any source without loading it into Perspective's tables:
18+
19+
- **[nodejs-virtual-server](nodejs-virtual-server/)** - Node.js example with in-memory data and WebSocket server
20+
- **[python-duckdb-virtual](python-duckdb-virtual/)** - Python example using DuckDB as a data source
21+
1522
# Optional
1623

1724
Generally, the changes necessary to make these examples run _without_ the

examples/blocks/examples.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
const LOCAL_EXAMPLES = [
1414
"editable",
1515
"file",
16+
"duckdb",
1617
"fractal",
1718
"market",
1819
"raycasting",

examples/blocks/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"version": "4.0.1",
55
"description": "A collection of simple client-side Perspective examples for `http://bl.ocks.org`.",
66
"scripts": {
7-
"start": "mkdir -p dist && node --experimental-wasm-memory64 --experimental-modules server.mjs",
7+
"start": "mkdir -p dist && node --experimental-modules server.mjs",
88
"repl": "node --experimental-repl-await"
99
},
1010
"main": "index.mjs",
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
An example of [Perspective](https://github.com/perspective-dev/perspective)
2+
using [DuckDB WASM](https://duckdb.org/docs/api/wasm/overview) as a virtual
3+
server backend via the `DuckDBHandler` adapter.
4+
5+
Instead of using Perspective's built-in WebAssembly query engine, this example
6+
demonstrates how to use DuckDB as the data processing layer while still
7+
leveraging Perspective's visualization components. The `DuckDBHandler` translates
8+
Perspective's view configuration (group by, split by, sort, filter, expressions,
9+
aggregates) into DuckDB SQL queries, enabling Perspective to query data stored
10+
in DuckDB tables.
11+
12+
This example loads the Superstore sample dataset into a DuckDB table, then
13+
creates a Perspective viewer that queries the data through the DuckDB virtual
14+
server. A separate log viewer displays the SQL queries being generated in
15+
real-time, along with a timeline chart showing query frequency.

examples/blocks/src/duckdb/index.css

Whitespace-only changes.
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<!doctype html>
2+
<html>
3+
<head>
4+
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no" />
5+
<link rel="preload" href="/node_modules/@perspective-dev/server/dist/wasm/perspective-server.wasm" as="fetch" type="application/wasm" crossorigin="anonymous" />
6+
<link rel="preload" href="/node_modules/@perspective-dev/viewer/dist/wasm/perspective-viewer.wasm" as="fetch" type="application/wasm" crossorigin="anonymous" />
7+
<link rel="preload" href="/node_modules/superstore-arrow/superstore.lz4.arrow" as="fetch" type="arraybuffer" crossorigin="anonymous" />
8+
<link rel="stylesheet" crossorigin="anonymous" href="/node_modules/@perspective-dev/viewer/dist/css/themes.css" />
9+
<script type="module" src="index.js"></script>
10+
<style>
11+
#query {
12+
position: absolute;
13+
top: 0;
14+
left: 0;
15+
bottom: 0;
16+
right: 30%;
17+
}
18+
19+
#logger {
20+
position: absolute;
21+
top: 40%;
22+
left: 70%;
23+
bottom: 0%;
24+
right: 0;
25+
}
26+
#logger2 {
27+
position: absolute;
28+
top: 0%;
29+
left: 70%;
30+
bottom: 60%;
31+
right: 0;
32+
}
33+
</style>
34+
</head>
35+
<body>
36+
<perspective-viewer id="query"></perspective-viewer>
37+
<perspective-viewer id="logger"></perspective-viewer>
38+
<perspective-viewer id="logger2"></perspective-viewer>
39+
</body>
40+
</html>

0 commit comments

Comments
 (0)