GQL graph queries, mutations, and algorithms over DuckDB and DuckLake tables
Compatibility Matrix
This table covers all DuckDB releases that have not reached end-of-life, 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
INSTALL duckgql FROM community;
LOAD duckgql;
Example
COPY (
SELECT * FROM (VALUES
('p1', 'Ada', 'Person'),
('p2', 'Grace', 'Person')
) nodes(":ID(People)", "name:string", ":LABEL")
) TO 'duckgql_nodes.csv' (FORMAT CSV, HEADER);
COPY (
SELECT * FROM (VALUES
('p1', 'p2', 'KNOWS')
) edges(":START_ID(People)", ":END_ID(People)", ":TYPE")
) TO 'duckgql_edges.csv' (FORMAT CSV, HEADER);
CREATE GRAPH social ANY;
COPY GRAPH social FROM (
VERTICES 'duckgql_nodes.csv',
EDGES 'duckgql_edges.csv'
) FORMAT GRAPH;
SESSION SET GRAPH social;
MATCH (person:Person)-[:KNOWS]->(friend:Person)
RETURN person.name, friend.name;
About duckgql
DuckGQL is an experimental C++17 extension that adds a growing subset of ISO/IEC 39075:2024 GQL to DuckDB. It combines graph pattern queries and mutations with DuckDB's native relational storage and execution engine, plus an explicit CSR layer for graph algorithms.
What works in v0.3.1
This version targets DuckDB 2.0.0.
- Managed property graphs backed by typed DuckDB vertex and edge tables.
- Zero-copy graph projections over existing DuckDB and DuckLake tables,
including multiple heterogeneous vertex and edge mappings. Live graphs
registered with
ACCESS_MODE 'READ_WRITE'support GQLINSERT,SET,REMOVE, andDELETEagainst their mapped source tables. - Live DuckLake projections that follow committed snapshots, or pinned projections for reproducible analysis.
- Mapping-scoped integer source keys, optional edge keys, and DuckGQL-managed dense element IDs, without application-maintained numeric ID ranges.
- Inline typed graph schemas that persist in the catalog and immediately
materialize constrained vertex and edge tables without
COPY GRAPH. - Graph-header CSV, compressed CSV, and Parquet bulk import with optional endpoint and identity validation.
- Directed
MATCH,OPTIONAL MATCH, filtering, projection, aggregation, ordering, paging, fixed multi-hop patterns, and a bounded variable-length path subset, composed quantified patterns, shortest-path search, and search-based reachability. - Standalone node and directed-path
INSERT, fixed directedMATCH-and-INSERT, multiple directed insertion paths, node and edgeINSERT RETURNvalues, property and label mutation, and edge/node deletion. - Query parameters and native DuckDB ART indexes for selective vertex-property equality lookups.
- Compact, buffer-managed CSR snapshots with incremental insert deltas and optional persistence in the database file for reuse after reopening.
- Explicit CSR-backed BFS, DFS, unweighted and weighted SSSP, PageRank, weak and strong components, Louvain community detection, degree, closeness, local clustering coefficient, and triangle counting.
- Experimental cost-based graph planning with plan diagnostics, directional
fanout and endpoint statistics, and costing across connected patterns.
Seed-degree estimates and same-type degree bias improve expansion costing.
Enable it with
SET gql_optimizer = 'cost'; legacy planning is the default. - Snapshot-scoped DuckLake identity caching and selective projected property access, with source-version pinning and prepared-query rebinding.
Storage and execution model
Managed vertices and edges remain authoritative ordinary DuckDB tables
rather than entity-attribute-value rows. For referenced graphs, the mapped
DuckDB or DuckLake source tables remain authoritative and DuckGQL persists
the typed graph mapping and derived caches. Nodes retain their complete label set and each
edge has exactly one immutable type. DuckGQL lowers graph queries to native
DuckDB relational plans, allowing DuckDB to execute scans, joins,
aggregation, ordering, and recursive CTEs. The graph optimizer can choose
table scans, native property indexes, node-label postings, and selective
CSR expansion. CSR snapshots are database-instance scoped, version checked,
and derived rather than authoritative. Inserts are read through a delta
alongside the snapshot; updates and deletes invalidate affected snapshots.
gql_build_csr saves snapshots in the database file by default. After
reopening, saved pages load on demand through DuckDB's buffer manager,
including for read-only databases. Use persist := false for memory-only
snapshots.
Project status
DuckGQL v0.3.1 is not yet a complete or conforming ISO GQL implementation. Grammar recognition does not imply semantic or transactional conformance. The machine-readable conformance manifest records partial and planned feature families. Important restrictions include autocommit-only graph lifecycle and CSR operations, a single vertex and edge input per bulk load, and incomplete general path searches, query composition, procedures, and the complete GQL value/type system.
See the documentation, inspect the conformance manifest, or try the browser playground.
Added Functions
| function_name | function_type | description | comment | examples |
|---|---|---|---|---|
| bfs | table | NULL | NULL | |
| closeness | table | NULL | NULL | |
| degree | table | NULL | NULL | |
| dfs | table | NULL | NULL | |
| gql_algorithm_call | table | NULL | NULL | |
| gql_algorithm_result | table | NULL | NULL | |
| gql_algorithm_stats | table | NULL | NULL | |
| gql_build_csr | table | NULL | NULL | |
| gql_cast_float | scalar | NULL | NULL | |
| gql_clear_properties_source | table | NULL | NULL | |
| gql_create_property_index | table | NULL | NULL | |
| gql_csr_all_shortest | table | NULL | NULL | |
| gql_csr_edge_stats | table | NULL | NULL | |
| gql_csr_endpoint_stats | table | NULL | NULL | |
| gql_csr_expand | table | NULL | NULL | |
| gql_csr_path_expand | table | NULL | NULL | |
| gql_csr_shortest_expand | table | NULL | NULL | |
| gql_csr_stats | table | NULL | NULL | |
| gql_csr_vertices | table | NULL | NULL | |
| gql_drop_property_index | table | NULL | NULL | |
| gql_edge_fetch | table | NULL | NULL | |
| gql_graphs | table | NULL | NULL | |
| gql_insert_ids | table | NULL | NULL | |
| gql_insert_result | table | NULL | NULL | |
| gql_insert_target | table | NULL | NULL | |
| gql_match_insert_ids | table | NULL | NULL | |
| gql_match_recursive | table | NULL | NULL | |
| gql_match_relational | table | NULL | NULL | |
| gql_merge_id | table | NULL | NULL | |
| gql_merge_target | table | NULL | NULL | |
| gql_mutation_control | table | NULL | NULL | |
| gql_mutation_graph | table | NULL | NULL | |
| gql_mutation_target | table | NULL | NULL | |
| gql_neighbors | table | NULL | NULL | |
| gql_optimizer_plan | table | NULL | NULL | |
| gql_property_indexes | table | NULL | NULL | |
| gql_referenced_cache_stats | table | NULL | NULL | |
| gql_referenced_keys | table | NULL | NULL | |
| gql_trail_unique | scalar | NULL | NULL | |
| gql_vertex_fetch | table | NULL | NULL | |
| gql_vertex_fetch_projected | table | NULL | NULL | |
| gql_vertex_lookup | table | NULL | NULL | |
| lcc | table | NULL | NULL | |
| louvain | table | NULL | NULL | |
| pagerank | table | NULL | NULL | |
| scc | table | NULL | NULL | |
| sssp | table | NULL | NULL | |
| triangle_count | table | NULL | NULL | |
| wcc | table | NULL | NULL | |
| weighted_sssp | table | NULL | NULL |
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 |
|---|---|---|---|---|---|
| allow_parser_override_extension | Allow extensions to override the current parser. | VARCHAR | GLOBAL | [] | fallback |
| gql_optimizer | Graph access planner: legacy (default) or experimental cost-based search | VARCHAR | GLOBAL | [] | legacy |
| temp_directory | Set the directory to which temporary files are written. | VARCHAR | GLOBAL | [] | post.db.tmp |