Official DuckDB Julia Package

DuckDB is a high-performance in-process analytical database system. It is designed to be fast, reliable and easy to use. For more information on the goals of DuckDB, please refer to the Why DuckDB page on our website.

The DuckDB Julia package provides a high-performance front-end for DuckDB. Much like SQLite, DuckDB runs in-process within the Julia client, and provides a DBInterface front-end.

The package also supports multi-threaded execution. It uses Julia threads/tasks for this purpose. If you wish to run queries in parallel, you must launch Julia with multi-threading support (by e.g. setting the JULIA_NUM_THREADS environment variable).


pkg> add DuckDB

julia> using DuckDB


# create a new in-memory database
con = DBInterface.connect(DuckDB.DB, ":memory:")

# create a table
DBInterface.execute(con, "CREATE TABLE integers(i INTEGER)")

# insert data using a prepared statement
stmt = DBInterface.prepare(con, "INSERT INTO integers VALUES(?)")
DBInterface.execute(stmt, [42])

# query the database
results = DBInterface.execute(con, "SELECT 42 a")

Scanning DataFrames

The DuckDB Julia package also provides support for querying Julia DataFrames. Note that the DataFrames are directly read by DuckDB - they are not inserted or copied into the database itself.

If you wish to load data from a DataFrame into a DuckDB table you can run a CREATE TABLE AS or INSERT INTO query.

using DuckDB
using DataFrames

# create a new in-memory dabase
con = DBInterface.connect(DuckDB.DB)

# create a DataFrame
df = DataFrame(a = [1, 2, 3], b = [42, 84, 42])

# register it as a view in the database
DuckDB.register_data_frame(con, df, "my_df")

# run a SQL query over the DataFrame
results = DBInterface.execute(con, "SELECT * FROM my_df")

Original Julia Connector

Credits to kimmolinna for the original DuckDB Julia connector.

Contributing to the Julia Package


The format script must be run when changing anything. This can be done by running the following command from within the root directory of the project:

julia tools/juliapkg/scripts/format.jl


You can run the tests using the script:


Specific test files can be run by adding the name of the file as an argument:

./ test_connection.jl


Build using DISABLE_SANITIZER=1 make debug

To run against a locally compiled version of duckdb, you'll need to set the JULIA_DUCKDB_LIBRARY environment variable, e.g.:

export JULIA_DUCKDB_LIBRARY="`pwd`/../../build/debug/src/libduckdb.dylib"

Note that Julia pre-compilation caching might get in the way of changes to this variable taking effect. You can clear these caches using the following command:

rm -rf ~/.julia/compiled

For development a few packages are required, these live in a Project.toml in the test directory, installed like so:

cd tools/juliapkg
using Pkg

Debugging using LLDB

Julia's builtin version management system juliaup can get in the way of starting a process with lldb attached as it provides a shim for the julia binary. The actual julia binaries live in ~/.julia/juliaup/<version>/bin/julia

lldb -- julia ... will likely not work and you'll need to provide the absolute path of the julia binary, e.g:

lldb -- ~/.julia/juliaup/ ...


To run the test suite in it's entirety:

julia -e "import Pkg; Pkg.activate(\".\"); include(\"test/runtests.jl\")"

To run a specific test listed in test/runtests.jl, you can provide the name, e.g:

julia -e "import Pkg; Pkg.activate(\".\"); include(\"test/runtests.jl\")" "test_basic_queries.jl"

Just as mentioned before, to attach lldb to this, you'll have to replace the julia part with the absolute path.

Submitting a New Package

The DuckDB Julia package depends on the DuckDB_jll package, which can be updated by sending a PR to Yggdrassil.

After the DuckDB_jll package is updated, the DuckDB package can be updated by incrementing the version number (and dependency version numbers) in Project.toml, followed by adding a comment containing the text @JuliaRegistrator register subdir=tools/juliapkg to the commit.