use duckdb::{
Connection, Result,
core::{DataChunkHandle, LogicalTypeHandle, LogicalTypeId},
vscalar::{ScalarFunctionSignature, VScalar},
vtab::arrow::WritableVector,
};
struct AddOne;
impl VScalar for AddOne {
type State = ();
fn invoke(
_: &Self::State,
input: &mut DataChunkHandle,
output: &mut dyn WritableVector,
) -> Result<(), Box<dyn std::error::Error>> {
let len = input.len();
let src = input.flat_vector(0);
let src = unsafe { src.as_slice_with_len::<i64>(len) };
let mut out = output.flat_vector();
let dst = unsafe { out.as_mut_slice_with_len::<i64>(len) };
for (d, s) in dst.iter_mut().zip(src) {
*d = s + 1;
}
Ok(())
}
fn signatures() -> Vec<ScalarFunctionSignature> {
vec![ScalarFunctionSignature::exact(
vec![LogicalTypeHandle::from(LogicalTypeId::Bigint)],
LogicalTypeHandle::from(LogicalTypeId::Bigint),
)]
}
}
fn main() -> Result<()> {
let conn = Connection::open_in_memory()?;
conn.register_scalar_function::<AddOne>("add_one")?;
let mut stmt = conn.prepare("SELECT add_one(i) FROM range(5) t(i)")?;
let values: Vec<i64> = stmt.query_map([], |row| row.get(0))?.collect::<Result<_>>()?;
println!("add_one(0..5) = {values:?}");
assert_eq!(values, vec![1, 2, 3, 4, 5]);
Ok(())
}