How to Connect to DuckDB with C++

🚀 A fast and futuristic database for your projects.


How to Connect to DuckDB with C++


We have already written an initial article about DuckDB that explains initial concepts, installation and first steps. For more information, access the link:

In this article, we will see how to connect to DuckDB using the API with C++


01. Download the lib and create a basic code

The DuckDB API for C++ is not yet stable, on the API page itself there is this warning:

DuckDB's C++ API is internal. It is not guaranteed to be stable and can change without notice. If you would like to build an application on DuckDB, we recommend using the C API.

That’s why they recommend that you use the C API which works perfectly. To do this, just access the page: https://duckdb.org/docs/installation/ and choose the data according to your system. In my case, I chose:

Then just click on the .zip that will be made available and download it, or download it with wget:

wget -q https://github.com/duckdb/duckdb/releases/download/v1.3.0/libduckdb-linux-amd64.zip

Unzip:

unzip libduckdb-linux-amd64.zip -d libduckdb-linux-amd64

Create a database and table, example: duckdb terminalroot.db

CREATE TABLE terminalroot (id INTEGER, name STRING);
INSERT INTO terminalroot VALUES(1, 'Marcos Oliveira');
INSERT INTO terminalroot VALUES(2, 'Mark Raasveldt');
INSERT INTO terminalroot VALUES(3, 'Hannes Muhleisen');
SELECT * FROM terminalroot;
.exit

Go into the directory you unzipped and create some basic code: cd libduckdb-linux-amd64/ && vim main.cpp

#include "duckdb.h"
#include <iostream>

int main(){
    duckdb_database db;
    duckdb_connection con;
    duckdb_result result;

    if(duckdb_open("terminalroot.db", &db) == DuckDBError){
        std::cerr << "Error opening database\n";
        return 1;
    }
    if(duckdb_connect(db, &con) == DuckDBError){
        std::cerr << "Error connecting to database\n";
        return 1; } 

    if(duckdb_query(con, "SELECT * FROM terminalroot;", &result) == DuckDBError){ 
        std::cerr << "Error executing SELECT\n"; 
        duckdb_disconnect(&con); 
        duckdb_close(&db); 
        return 1; 
    } 

    for(idx_t row = 0; row <= result.deprecated_column_count; row++){ 
        int id = duckdb_value_int32(&result, 0, row); 
        const char* name = duckdb_value_varchar(&result, 1, row); 
        std::cout << id << " | " << name << '\n'; 
        duckdb_free((void*)name); // free varchar memory 
    } 

    duckdb_destroy_result(&result); 
    duckdb_disconnect(&con);
    duckdb_close(&db);
}

Compile and run:

g++ main.cpp libduckdb.so
LD_LIBRARY_PATH=. ./a.out

Probable output:

1 | Marcos Oliveira
2 | Mark Raasveldt
3 | Hannes Muhleisen

Install on the system

If you want to install on your system and compile with the -lduckdb flag, run the commands below:

  • 01. Move .h to include:
sudo mkdir -p /usr/local/include/duckdb
sudo cp duckdb.h /usr/local/include/duckdb/
  • 02. Move the dynamic library to lib

    And update the system’s shared library cache.

sudo cp libduckdb.so /usr/local/lib/
sudo ldconfig

After that, just test with the flag and you don’t even need to be in the folder with the downloaded files or use the LD_LIBRARY_PATH environment variable:

But you need terminalroot.db, if you put the absolute path, e.g.: "/home/$USER/.db/terminalroot.db" your binary will run regardless of where you are in the system!

g++ main.cpp -lduckdb
./a.out

If you want to create .pc for pkg-config, expand the procedure below:

Create the file /usr/local/lib/pkgconfig/duckdb.pc with this content:
prefix=/usr/local
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include

Name: DuckDB
Description: DuckDB embedded database
Version: 1.2.1
Libs: -L${libdir} -lduckdb
Cflags: -I${includedir}/duckdb

Save with:

sudo mkdir -p /usr/local/lib/pkgconfig
sudo vim /usr/local/lib/pkgconfig/duckdb.pc
# paste the above content

Refresh the cache:

export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig:$PKG_CONFIG_PATH


I tried the static library libduckdb_static.a, but had problems, but if you prefer, try:

g++ main.cpp libduckdb_static.a -I. -ldl -pthread -lm -lz -static-libstdc++ -static-libgcc

If you also have problems, check for missing dependencies:

nm libduckdb_static.a | grep " U "

("U" = undefined symbol)

Or use ldd ./a.out to see if there are still dynamic libs hanging.

In my case none of these steps worked, but see if they apply to you too.



duckdb sql cpp


Share


YouTube channel

Subscribe


Marcos Oliveira

Marcos Oliveira

Software developer
https://github.com/terroo

Related articles