Skip to content

Commit 524ab28

Browse files
authored
duckdb: conversion docs (#3519)
Signed-off-by: Alexander Droste <alexander.droste@protonmail.com>
1 parent b3ec563 commit 524ab28

File tree

2 files changed

+102
-1
lines changed

2 files changed

+102
-1
lines changed

vortex-duckdb-ext/src/convert/dtype.rs

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,30 @@
1+
//! Logical type conversion between Vortex and DuckDB.
2+
//!
3+
//! This module provides functionality to convert Vortex data types (`DType`) to DuckDB logical types.
4+
//!
5+
//! Note that nullability of Vortex logical types is not transferred to DuckDB logical types.
6+
//!
7+
//! # Supported Type Mappings
8+
//!
9+
//! | Vortex Type | DuckDB Type |
10+
//! |-------------|-------------|
11+
//! | `Null` | `SQLNULL` |
12+
//! | `Bool` | `BOOLEAN` |
13+
//! | `I8/U8` | `TINYINT/UTINYINT` |
14+
//! | `I16/U16` | `SMALLINT/USMALLINT` |
15+
//! | `I32/U32` | `INTEGER/UINTEGER` |
16+
//! | `I64/U64` | `BIGINT/UBIGINT` |
17+
//! | `F32` | `FLOAT` |
18+
//! | `F64` | `DOUBLE` |
19+
//! | `Utf8` | `VARCHAR` |
20+
//! | `Binary` | `BLOB` |
21+
//! | `Struct` | `STRUCT` |
22+
//! | `Decimal` | `DECIMAL` |
23+
//! | `List` | `LIST` |
24+
//! | `Date` | `DATE` |
25+
//! | `Time` | `TIME` |
26+
//! | `Timestamp` | `TIMESTAMP` |
27+
128
use std::ffi::CString;
229

330
use vortex::dtype::{DType, PType, datetime};
@@ -7,6 +34,7 @@ use crate::cpp::{self, duckdb_logical_type};
734
use crate::duckdb::LogicalType;
835

936
impl LogicalType {
37+
/// Creates a DuckDB struct logical type from child types and field names.
1038
fn struct_type<T, N>(child_types: T, child_names: N) -> VortexResult<LogicalType>
1139
where
1240
T: IntoIterator<Item = LogicalType>,
@@ -36,6 +64,7 @@ impl LogicalType {
3664
Ok(unsafe { Self::own(struct_type_ptr) })
3765
}
3866

67+
/// Creates a DuckDB decimal logical type with the specified precision and scale.
3968
fn decimal_type(precision: u8, scale: u8) -> VortexResult<Self> {
4069
assert!(
4170
precision <= 38,
@@ -51,6 +80,7 @@ impl LogicalType {
5180
}
5281
}
5382

83+
/// Creates a DuckDB list logical type with the specified element type.
5484
fn list_type(element_type: LogicalType) -> VortexResult<Self> {
5585
unsafe {
5686
let ptr = cpp::duckdb_create_list_type(element_type.as_ptr());
@@ -61,7 +91,17 @@ impl LogicalType {
6191
}
6292
}
6393

64-
/// Convert temporal extension types to corresponding DuckDB types.
94+
/// Converts temporal extension types to corresponding DuckDB types.
95+
///
96+
/// # Arguments
97+
///
98+
/// * `ext_dtype` - A reference to the extension data type containing temporal metadata.
99+
///
100+
/// # Supported Temporal Types
101+
///
102+
/// - **Date**: Must use `TimeUnit::D`
103+
/// - **Time**: Must use `TimeUnit::Us`
104+
/// - **Timestamp**: Supports `TimeUnit::Ns`, `Us`, `Ms`, `S`
65105
fn temporal_type(ext_dtype: &vortex::dtype::ExtDType) -> VortexResult<Self> {
66106
use vortex::dtype::datetime::{TemporalMetadata, TimeUnit};
67107

@@ -98,6 +138,18 @@ impl LogicalType {
98138
impl TryFrom<&DType> for LogicalType {
99139
type Error = VortexError;
100140

141+
/// Converts a Vortex data type to a DuckDB logical type.
142+
///
143+
/// This is the main conversion function that handles all supported Vortex data types
144+
/// and maps them to their corresponding DuckDB logical types.
145+
///
146+
/// # Arguments
147+
///
148+
/// * `dtype` - A reference to the Vortex data type to convert
149+
///
150+
/// # Returns
151+
///
152+
/// A `Result` containing the DuckDB logical type or a conversion error.
101153
fn try_from(dtype: &DType) -> Result<Self, Self::Error> {
102154
let duckdb_type = match dtype {
103155
DType::Null => cpp::DUCKDB_TYPE::DUCKDB_TYPE_SQLNULL,

vortex-duckdb-ext/src/convert/scalar.rs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,21 @@
1+
//! Scalar value conversion between Vortex and DuckDB.
2+
//!
3+
//! This module provides functionality to convert Vortex scalar values to DuckDB values.
4+
//!
5+
//! Note that nullability of Vortex scalars is not transferred to DuckDB scalars.
6+
//!
7+
//! # Supported Scalar Conversions
8+
//!
9+
//! | Vortex Scalar | DuckDB Value |
10+
//! |---------------|--------------|
11+
//! | `Null` | `NULL` |
12+
//! | `Bool` | `BOOLEAN` |
13+
//! | `Primitive` (integers/floats) | Corresponding numeric types |
14+
//! | `Decimal` | `DECIMAL` |
15+
//! | `Utf8` | `VARCHAR` |
16+
//! | `Binary` | `BLOB` |
17+
//! | `ExtScalar` (temporal) | `DATE`/`TIME`/`TIMESTAMP` |
18+
119
use vortex::dtype::datetime::{TemporalMetadata, TimeUnit};
220
use vortex::dtype::half::f16;
321
use vortex::dtype::{DType, PType, match_each_native_simd_ptype};
@@ -9,12 +27,22 @@ use vortex::scalar::{
927

1028
use crate::duckdb::Value;
1129

30+
/// Trait for converting Vortex scalars to DuckDB values.
1231
pub trait ToDuckDBScalar {
1332
fn try_to_duckdb_scalar(&self) -> VortexResult<Value>;
1433
}
1534

1635
impl ToDuckDBScalar for Scalar {
36+
/// Converts a generic Vortex scalar to a DuckDB value.
37+
///
38+
/// # Note
39+
///
40+
/// Struct and List scalars are not yet implemented and cause a panic.
1741
fn try_to_duckdb_scalar(&self) -> VortexResult<Value> {
42+
if self.is_null() {
43+
return Ok(Value::null());
44+
}
45+
1846
match self.dtype() {
1947
DType::Null => Ok(Value::null()),
2048
DType::Bool(_) => self.as_bool().try_to_duckdb_scalar(),
@@ -29,6 +57,11 @@ impl ToDuckDBScalar for Scalar {
2957
}
3058

3159
impl ToDuckDBScalar for PrimitiveScalar<'_> {
60+
/// Converts a primitive scalar (integer, float, or boolean) to a DuckDB value.
61+
///
62+
/// # Note
63+
///
64+
/// - `F16` values are converted to `F32` before creating the DuckDB value
3265
fn try_to_duckdb_scalar(&self) -> VortexResult<Value> {
3366
if self.ptype() == PType::F16 {
3467
return Ok(Value::from(
@@ -46,6 +79,18 @@ impl ToDuckDBScalar for PrimitiveScalar<'_> {
4679
}
4780

4881
impl ToDuckDBScalar for DecimalScalar<'_> {
82+
/// Converts a decimal scalar to a DuckDB decimal value.
83+
///
84+
/// # Supported Decimal Types
85+
///
86+
/// - `I8`, `I16`, `I32`, `I64` - Converted to `i128` for DuckDB
87+
/// - `I128` - Used directly
88+
/// - `I256` - Not supported, returns an error
89+
///
90+
/// # Note: Scalar vs Array Conversion Differences
91+
///
92+
/// This scalar conversion always uses `i128` for all decimal values regardless of precision,
93+
/// which differs from the array conversion logic that uses precision-based storage optimization.
4994
fn try_to_duckdb_scalar(&self) -> VortexResult<Value> {
5095
let decimal_type = self
5196
.dtype()
@@ -74,12 +119,14 @@ impl ToDuckDBScalar for DecimalScalar<'_> {
74119
}
75120

76121
impl ToDuckDBScalar for BoolScalar<'_> {
122+
/// Converts a boolean scalar to a DuckDB boolean value.
77123
fn try_to_duckdb_scalar(&self) -> VortexResult<Value> {
78124
Ok(Value::from(self.value()))
79125
}
80126
}
81127

82128
impl ToDuckDBScalar for Utf8Scalar<'_> {
129+
/// Converts a UTF-8 string scalar to a DuckDB VARCHAR value.
83130
fn try_to_duckdb_scalar(&self) -> VortexResult<Value> {
84131
Ok(match self.value() {
85132
Some(value) => Value::from(value.as_str()),
@@ -89,6 +136,7 @@ impl ToDuckDBScalar for Utf8Scalar<'_> {
89136
}
90137

91138
impl ToDuckDBScalar for BinaryScalar<'_> {
139+
/// Converts a binary scalar to a DuckDB BLOB value.
92140
fn try_to_duckdb_scalar(&self) -> VortexResult<Value> {
93141
Ok(match self.value() {
94142
Some(value) => Value::from(value.as_slice()),
@@ -98,6 +146,7 @@ impl ToDuckDBScalar for BinaryScalar<'_> {
98146
}
99147

100148
impl ToDuckDBScalar for ExtScalar<'_> {
149+
/// Converts an extension scalar (primarily temporal types) to a DuckDB value.
101150
fn try_to_duckdb_scalar(&self) -> VortexResult<Value> {
102151
let time = TemporalMetadata::try_from(self.ext_dtype())?;
103152
let value = || {

0 commit comments

Comments
 (0)