src/— Core C++ source code (catalog, common, execution, function, main, optimizer, parallel, parser, planner, storage, transaction)src/include/— Header filesextension/— In-tree extensions (parquet, json, icu, tpch, tpcds, autocomplete, core_functions, jemalloc, delta)test/— Tests (sqllogictest.testfiles and C++ unit tests)test/sql/— SQL-based tests organized by category (aggregate, join, cast, function, etc.)third_party/— Third-party dependenciestools/— Language bindings and toolsscripts/— Build and CI scripts.github/config/— CI extension build configurations
DuckDB uses CMake + Make. Always run from the repo root.
# Release build (default)
make
# Debug build (includes sanitizers and DEBUG_MOVE)
make debug
# RelWithDebInfo + assertions (used in CI smoke tests)
make relassert
# Use Ninja for faster parallel builds
GEN=ninja make
# Limit parallel build jobs if system runs out of memory
CMAKE_BUILD_PARALLEL_LEVEL=4 GEN=ninja make
# Build with specific extensions
BUILD_EXTENSIONS="httpfs;json;icu" make
# Build all in-tree extensions (same as CI)
EXTENSION_CONFIGS=.github/config/in_tree_extensions.cmake make
# Build all extensions including out-of-tree (requires vcpkg)
BUILD_ALL_EXT=1 makeBuild outputs go to build/<type>/ (e.g., build/debug/, build/release/).
The build system automatically detects and uses ccache or sccache if installed — use them to speed up rebuilds.
The CI pipeline builds these in-tree extensions (.github/config/in_tree_extensions.cmake):
autocomplete,core_functions,icu,json,parquet,tpcds,tpch
The base config (extension/extension_config.cmake) always includes: core_functions, parquet (and jemalloc on 64-bit Linux).
For local extension customization, create extension/extension_config_local.cmake (git-ignored).
IMPORTANT: Never run all tests at once. Always run specific tests or test groups.
# Debug build
build/debug/test/unittest "test/sql/aggregate/aggregates/my_test.test"
# Release build
build/release/test/unittest "test/sql/aggregate/aggregates/my_test.test"# Run tests matching a tag
build/debug/test/unittest "[sql]"
# Run tests matching a pattern
build/debug/test/unittest "*test_name*"# With a test config (e.g., verification enabled)
build/debug/test/unittest "test/path/to/test.test" --test-config="test/configs/enable_verification.json"Available test configs are in test/configs/ (e.g., enable_verification.json, force_storage.json, latest_storage.json, verify_fetch_row.json).
# Run all tests via the CI runner (parallel, with batching)
python3 scripts/ci/run_tests.py build/relassert/test/unittest
# Run smoke tests
make smoke
# Run with a specific test filter
python3 scripts/ci/run_tests.py build/relassert/test/unittest "pattern".test— Standard sqllogictest files (run in fast test suite).test_slow— Slower tests (run only inallunit/ nightly CI)
Strongly prefer writing tests as sqllogictest .test files rather than C++ tests. Only use C++ for tests requiring concurrent connections or exotic behavior.
# Check formatting
make format-check
# Fix formatting (run before submitting PRs)
make format-fix
# Format only changed files (relative to main)
make format-mainUses clang-format 11.0.1 and black. Install with: python3 -m pip install clang-format==11.0.1
Rules: tabs for indentation, spaces for alignment, 120 column max line length.
Some source files are auto-generated. After modifying schemas or adding settings/functions:
make generate-filesThis runs several Python scripts to regenerate C API bindings, function registrations, settings, serialization code, etc.
- Use
duckdbnamespace for all code insrc/ - Use
unique_ptrovershared_ptr; no rawnew/delete/malloc - Use
[u]int(8|16|32|64)_tfor sized integers,idx_tfor indices/counts - CamelCase for types and functions, snake_case for variables and files
- Use
D_ASSERTfor programmer-error assertions (never triggered by user input) - Use exceptions only for query-terminating errors
overrideorfinalon virtual method overrides; never repeatvirtual- Do not
using namespace std
- Debug builds include AddressSanitizer and UBSan by default. Disable with
DISABLE_SANITIZER=1 make debug - Use
FORCE_ASSERT=1in release builds to enable assertions without full debug overhead - The
relassertbuild type is RelWithDebInfo + assertions — good balance of speed and safety - Use
--test-temp-dir <path>with unittest to preserve test artifacts for inspection
- PR checks: format check, debug build + fast unit tests, release build + all unit tests
- Nightly: extended tests, package builds, storage compatibility checks
- Extension builds use configs from
.github/config/
- Do NOT run the DuckDB CLI with queries that may run forever (e.g., complex aggregation queries). Use the unittest binary for testing.
- Do NOT run
make allunit— it takes ~1 hour. Run specific tests instead.
- Never add Claude as a co-author in commit messages. Do not include
Co-authored-by: Claudeor any similar line attributing Claude as a contributor.