--- warning: DO NOT CHANGE THIS MANUALLY, THIS IS GENERATED BY https://github.com/duckdb/community-extensions repository, check README there title: duckfn_kuva excerpt: | DuckDB Community Extensions Statistical plotting in SQL - a thin wrapper around the Rust library kuva, with the statistical semantics of seaborn and ggplot2 but no Python or R environment, on every platform DuckDB runs (console, JVM, Python, Node, browser) extension: name: duckfn_kuva description: Statistical plotting in SQL - a thin wrapper around the Rust library kuva, with the statistical semantics of seaborn and ggplot2 but no Python or R environment, on every platform DuckDB runs (console, JVM, Python, Node, browser) version: 0.3.0 language: Rust build: cargo license: MIT requires_toolchains: "rust;python3" maintainers: - shijianjs repo: github: shijianjs/duckfn-kuva ref: 5fd677c70d5572f61eab5d44ce9a157708d15486 ref_next: 5fd677c70d5572f61eab5d44ce9a157708d15486 docs: hello_world: | -- One function: a JSON chart spec in, an SVG document out SELECT kuva_render('{"series":[{"type":"scatter","data":[{"x":1,"y":2},{"x":3,"y":4},{"x":5,"y":3}]}]}'); -- ... -- Several series overlay on one set of axes SELECT kuva_render('{"series":[{"type":"line","data":[{"x":0,"y":1},{"x":1,"y":2},{"x":2,"y":1.5}],"legend":"signal"},{"type":"scatter","data":[{"x":0,"y":1.2},{"x":1,"y":1.8},{"x":2,"y":1.6}],"legend":"observed"}]}'); -- ... -- Or a multi-panel figure grid SELECT kuva_render('{"figure":{"rows":1,"cols":2,"panels":[{"series":[{"type":"scatter","data":[{"x":1,"y":2},{"x":2,"y":3}]}]},{"series":[{"type":"histogram","values":[1,2,2,3,3,3,4],"bins":4}]}]}}'); -- ... -- The chart config and the data can be separate: pass a dataset registry as the second argument SELECT kuva_render('{"series":[{"type":"scatter","dataset":"d","encode":{"x":"a","y":"b"}}]}', '{"d":[{"a":1,"b":2},{"a":3,"b":4}]}'); -- ... extended_description: | Renders statistical charts from SQL. The extension wraps the Rust plotting library kuva (SVG backend only) and exposes it through five scalar functions, so charts work anywhere DuckDB runs - the CLI, a Python or R session, the JVM, or the browser build (DuckDB-Wasm) - from one and the same extension binary. There is no matplotlib or ggplot2 in the loop, and no plotting environment to install. | Function | Kind | Input -> output | | --- | --- | --- | | `kuva_render(spec)` | scalar | `VARCHAR` (a JSON chart spec) -> `VARCHAR` (an SVG document) | | `kuva_render_terminal(spec)` | scalar | `VARCHAR` -> `VARCHAR` (terminal text: braille dots and ANSI colour) | | `kuva_render_typst(spec)` | scalar | `VARCHAR` -> `VARCHAR` (Typst source: a `.typ` CETZ document for `typst compile`) | | `kuva_render_file(spec)` | scalar | `VARCHAR` -> `VARCHAR` (the path of the SVG file it wrote; native builds only) | | `kuva_version()` | scalar | `-> VARCHAR` (the kuva version the loaded build was compiled against) | All four render functions take the same JSON spec, and all four also take an optional second argument: a JSON object mapping dataset names to arrays of rows, so the chart config and the data can be built by different things - the config by a host SDK, the data by SQL. A series names a dataset with `dataset` and maps its columns with `encode` (roles like `x`, `y`, `value`, `name`, `group`); the one-argument form is unchanged. Their own options stay in the JSON: `kuva_render_terminal` reads a top-level `terminal` object (`cols` / `rows` / `print`) and `kuva_render_file` reads a top-level `file` object (`dir` / `name` / `open`), which is what lets one statement write a chart to disk and optionally open it in a browser. `kuva_render_typst` has no options object: it returns Typst source (a CETZ vector drawing) that you compile yourself with `typst compile`. The JSON spec uses snake_case keys and describes the drawing rather than one particular chart. The top-level keys are `title`, `x_axis`, `y_axis`, `grid`, `legend`, `theme`, `palette`, `font`, `annotations`, `width`, `height` and `series` (or `figure` / `composite` instead of `series`). Every `series` entry carries a `type` from the table below and declares only the fields that type needs, so a scatter takes `data` as `{"x":…, "y":…}` objects with optional `x_err` / `y_err`, a bar takes `categories` plus `values` (or several named `series` for grouped and stacked bars), a histogram takes `values` with optional `bins` and a `kde` overlay, a box takes `groups` of raw values, and a pie takes `slices`. | Group | `type` values | | --- | --- | | Distributions | `histogram` `histogram2d` `density` `ridgeline` `ecdf` `qq` `box` `violin` `strip` `raincloud` `hexbin` `heatmap` | | Relationships & correlation | `scatter` `line` `series` `band` `jointplot` `contour` `parallel` `polar` `ternary` `quiver` | | Categorical & comparison | `bar` `pie` `waffle` `funnel` `pareto` `pyramid` `lollipop` `slope` `dot_plot` `dice_plot` `venn` `mosaic` `rose` `radar` `upset` | | Time series | `stacked_area` `streamgraph` `candlestick` `waterfall` `horizon` `calendar` `gantt` `bump` | | Statistical & model evaluation | `roc` `pr` `survival` `forest` `volcano` `manhattan` | | Hierarchical & network | `treemap` `sunburst` `network` `sankey` `chord` `phylo` `clustermap` | | 3D | `scatter3d` `surface3d` | | Composite & utility | `brick` `synteny` `text` `legend_plot` | JSON rather than a STRUCT is deliberate: the series of one figure are heterogeneous, and a STRUCT list cannot hold a mix of them. Composition works three ways. Several series in one `series` array are overlaid on a shared set of axes - a line with its scatter points on top, for instance. A top-level `figure` with `rows`, `cols` and `panels` switches to a multi-panel grid with shared axes and an optional shared legend. A top-level `composite` object draws a genome-browser coverage figure or a population allele-frequency figure (`type: coverage` or `brick_pop`); it is mutually exclusive with `series` and `figure`, carries its own canvas size and does not read a dataset. `theme` selects light, dark, minimal or solarized (or overrides individual colours), `palette` selects one of the named palettes or an explicit colour list, and `annotations` adds reference lines, shaded regions and text callouts. `grid` and `legend` cover the axis chrome, tick formats, grayscale (accessibility) mode and legend placement; `width`, `height` and `scale` size the canvas. A malformed spec fails the query with an actionable message rather than returning NULL, so a typo is never silent - for example a bar whose `values` and `categories` differ in length is rejected before anything is drawn. Requires **DuckDB 1.3 or newer**: the extension is built against DuckDB 1.5.6 headers but declares the C API floor it needs (v1.2.0), so one binary loads into 1.3.2 through 1.5.6 alike. The full field reference and the development notes live in the repository: . extension_star_count: 0 extension_star_count_pretty: 0 extension_download_count: 778 extension_download_count_pretty: 778 image: '/images/community_extensions/social_preview/preview_community_extension_duckfn_kuva.png' layout: community_extension_doc --- ### Compatibility Matrix This table covers all DuckDB releases that have not reached [end-of-life](https://duckdb.org/release_calendar), including LTS releases, and shows the 2 most recent patch releases of each. Older patch releases are not listed, but the extension may be available for them as well.
| Platform | 1.4.4 | 1.4.5 | 1.5.5 | 1.5.6 | 2.0.0 | | :--- | :---: | :---: | :---: | :---: | :---: | | Linux AMD64 | ❌ | ❌ | ❌ | ✅ | ✅ | | Linux ARM64 | ❌ | ❌ | ❌ | ✅ | ✅ | | macOS AMD64 | ❌ | ❌ | ❌ | ✅ | ✅ | | macOS ARM64 | ❌ | ❌ | ❌ | ✅ | ✅ | | Windows AMD64 | ❌ | ❌ | ❌ | ✅ | ✅ | | Windows ARM64 | ❌ | ❌ | ❌ | ❌ | ❌ | | WebAssembly | ❌ | ❌ | ❌ | ✅ | ✅ | ### Installing and Loading ```sql INSTALL {{ page.extension.name }} FROM community; LOAD {{ page.extension.name }}; ``` {% if page.docs.hello_world %} ### Example ```sql {{ page.docs.hello_world }}``` {% endif %} {% if page.docs.extended_description %} ### About {{ page.extension.name }} {{ page.docs.extended_description }} {% endif %} ### Added Functions
| function_name | function_type | description | comment | examples | |----------------------|---------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | kuva_render | scalar | Renders a complete chart described by a JSON string into an SVG document | The full-featured, JSON-based entry point: one JSON object describes canvas, axes, legend, annotations and a heterogeneous list of series; an optional second argument is a JSON object mapping dataset names to arrays of rows, which a series names with `dataset` and maps with `encode` | [SELECT kuva_render('{"series":[{"type":"scatter","dataset":"sales","encode":{"x":"revenue","y":"profit"{% raw %}}}{% endraw %}]}', '{"sales":[{"revenue":10,"profit":3},{"revenue":12,"profit":5}]}'); SELECT kuva_render('{"series":[{"type":"scatter","data":[{"x":1,"y":2},{"x":3,"y":4},{"x":5,"y":3}]}]}')] | | kuva_render_file | scalar | Renders a chart described by a JSON string to an SVG file and returns the file path; the JSON's own `file` object sets the directory, the file name and whether to open it in a browser | Native builds only: writes the SVG to disk (default: a file in the system temp directory, created if the directory is missing) and optionally opens it in the system default browser; `file: {dir, name, open}` rides along in the JSON, and an optional second argument supplies the data as a JSON dataset registry | [SELECT kuva_render_file('{"series":[{"type":"scatter","dataset":"d","encode":{"x":"a","y":"b"{% raw %}}}{% endraw %}]}', '{"d":[{"a":1,"b":2},{"a":3,"b":4}]}'); SELECT kuva_render_file('{"file":{"dir":"/tmp/charts","name":"scatter.svg","open":true},"series":[{"type":"scatter","data":[{"x":1,"y":2},{"x":3,"y":4}]}]}')] | | kuva_render_terminal | scalar | Renders a chart described by a JSON string as terminal text (braille dots and ANSI colour); the JSON's own `terminal` object sets the character grid and whether to print straight to stdout | Same JSON as kuva_render, different backend: `terminal: {cols, rows, print}` — a braille cell is 2x4 dots, defaults are 100x30, and `print: true` writes to stdout and returns NULL; an optional second argument supplies the data as a JSON dataset registry | [SELECT kuva_render_terminal('{"series":[{"type":"bar","dataset":"t","encode":{"name":"k","value":"v"{% raw %}}}{% endraw %}]}', '{"t":[{"k":"a","v":4},{"k":"b","v":7}]}'); SELECT kuva_render_terminal('{"terminal":{"cols":100,"rows":30},"series":[{"type":"line","data":[{"x":1,"y":2},{"x":2,"y":3}]}]}')] | | kuva_render_typst | scalar | Renders a chart described by a JSON string as a Typst source document (a CETZ vector drawing) for `typst compile` | Same JSON as kuva_render, different backend: the result is a `.typ` document (page setup + an `@preview/cetz` import + CETZ primitives). kuva does not embed a Typst compiler, so run `typst compile` on the returned source to get PDF / SVG / PNG; an optional second argument supplies the data as a JSON dataset registry | [SELECT kuva_render_typst('{"series":[{"type":"bar","dataset":"t","encode":{"name":"k","value":"v"{% raw %}}}{% endraw %}]}', '{"t":[{"k":"a","v":4},{"k":"b","v":7}]}'); SELECT kuva_render_typst('{"series":[{"type":"line","data":[{"x":1,"y":2},{"x":2,"y":3}]}]}')] | | kuva_version | scalar | Returns the kuva version this extension was compiled against | Useful when triaging an old figure: the SVG also records the version in a comment, but this answers it for the extension that is loaded right now | [SELECT kuva_version()] | ### Overloaded Functions
This extension does not add any function overloads. ### Added Types
This extension does not add any types. ### Added Settings
| name | description | input_type | scope | aliases | typed_value | |----------------|---------------------------------------------------------|------------|--------|---------|-------------| | temp_directory | Set the directory to which temporary files are written. | VARCHAR | GLOBAL | [] | post.db.tmp |