Selection Vectors

Requires the duckdb-1-5 feature flag (DuckDB 1.5.0+).

A SelectionVector is a list of row indices used to logically reorder or filter a data vector without copying its payload — the building block behind DuckDB's zero-copy filtering. Extensions that implement custom filtering or reordering in vectorized callbacks can allocate one, fill in the indices, and hand its raw handle to the relevant DuckDB vector operations.

This is an advanced, low-level primitive; most extensions never need it.

Allocating and filling

#![allow(unused)]
fn main() {
use quack_rs::selection_vector::SelectionVector;

fn demo() -> Result<(), quack_rs::error::ExtensionError> {
// Select source rows 3, 1, 4, 1, 5 (in that order) — note repeats are allowed.
let mut sel = SelectionVector::new(5)?;
sel.as_mut_slice().copy_from_slice(&[3, 1, 4, 1, 5]);

assert_eq!(sel.len(), 5);
assert_eq!(sel.as_slice(), &[3, 1, 4, 1, 5]);
Ok(())
}
}

The indices are 32-bit (sel_t / u32) and are zeroed by new — DuckDB itself leaves them uninitialised, so the wrapper clears them to keep as_slice() from exposing stale heap contents. Fill them via as_mut_slice().

new returns Err for a length above selection_vector::MAX_LEN: 2^32 (the range of sel_t) on 64-bit targets, and the largest u32 slice that fits in isize::MAX bytes on 32-bit ones. DuckDB does not check the length itself: a large enough length overflows its allocation-size arithmetic into a tiny buffer, and a request of 2^48 bytes or more makes its allocator throw, which would abort the extension.

API

MethodDescription
SelectionVector::new(size)Allocate size zeroed indices; Err above MAX_LEN
len() / is_empty()Number of indices
as_slice()&[u32] — read the indices
as_mut_slice()&mut [u32] — fill the indices
as_raw()The raw duckdb_selection_vector handle for DuckDB vector ops

SelectionVector is RAII: it is destroyed on drop.