Skip to content

Commit 9af377a

Browse files
authored
feat: create struct & decimal types for virtual tables (#246)
* build: switch to https url for submodule * enable struct code * add LogicalType#decimal * feat: more decimal methods * more struct tests * chore: satify clippy remove dud enumerate call * test more cases * correct docs
1 parent 897cd67 commit 9af377a

File tree

2 files changed

+74
-21
lines changed

2 files changed

+74
-21
lines changed

.gitmodules

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
[submodule "libduckdb-sys/duckdb-sources"]
22
path = libduckdb-sys/duckdb-sources
3-
url = git@github.com:duckdb/duckdb.git
4-
update = none
3+
url = https://github.com/duckdb/duckdb
4+
update = none

src/vtab/logical_type.rs

Lines changed: 72 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
use std::{ffi::CString, fmt::Debug};
1+
use std::{
2+
ffi::{c_char, CString},
3+
fmt::Debug,
4+
};
25

36
use crate::ffi::*;
47

@@ -176,25 +179,43 @@ impl LogicalType {
176179
}
177180
}
178181

182+
/// Creates a decimal type from its `width` and `scale`.
183+
pub fn decimal(width: u8, scale: u8) -> Self {
184+
unsafe {
185+
Self {
186+
ptr: duckdb_create_decimal_type(width, scale),
187+
}
188+
}
189+
}
190+
191+
/// Retrieves the decimal width
192+
/// Returns 0 if the LogicalType is not a decimal
193+
pub fn decimal_width(&self) -> u8 {
194+
unsafe { duckdb_decimal_width(self.ptr) }
195+
}
196+
197+
/// Retrieves the decimal scale
198+
/// Returns 0 if the LogicalType is not a decimal
199+
pub fn decimal_scale(&self) -> u8 {
200+
unsafe { duckdb_decimal_scale(self.ptr) }
201+
}
202+
179203
/// Make a `LogicalType` for `struct`
180-
// pub fn struct_type(fields: &[(&str, LogicalType)]) -> Self {
181-
// let keys: Vec<CString> = fields.iter().map(|f| CString::new(f.0).unwrap()).collect();
182-
// let values: Vec<duckdb_logical_type> = fields.iter().map(|it| it.1.ptr).collect();
183-
// let name_ptrs = keys
184-
// .iter()
185-
// .map(|it| it.as_ptr())
186-
// .collect::<Vec<*const c_char>>();
187-
188-
// unsafe {
189-
// Self {
190-
// ptr: duckdb_create_struct_type(
191-
// fields.len() as idx_t,
192-
// name_ptrs.as_slice().as_ptr().cast_mut(),
193-
// values.as_slice().as_ptr(),
194-
// ),
195-
// }
196-
// }
197-
// }
204+
pub fn struct_type(fields: &[(&str, LogicalType)]) -> Self {
205+
let keys: Vec<CString> = fields.iter().map(|f| CString::new(f.0).unwrap()).collect();
206+
let values: Vec<duckdb_logical_type> = fields.iter().map(|it| it.1.ptr).collect();
207+
let name_ptrs = keys.iter().map(|it| it.as_ptr()).collect::<Vec<*const c_char>>();
208+
209+
unsafe {
210+
Self {
211+
ptr: duckdb_create_struct_type(
212+
values.as_slice().as_ptr().cast_mut(),
213+
name_ptrs.as_slice().as_ptr().cast_mut(),
214+
fields.len() as idx_t,
215+
),
216+
}
217+
}
218+
}
198219

199220
/// Logical type ID
200221
pub fn id(&self) -> LogicalTypeId {
@@ -228,3 +249,35 @@ impl LogicalType {
228249
Self::from(c_logical_type)
229250
}
230251
}
252+
253+
#[cfg(test)]
254+
mod test {
255+
use crate::vtab::LogicalType;
256+
257+
#[test]
258+
fn test_struct() {
259+
let fields = &[("hello", LogicalType::new(crate::vtab::LogicalTypeId::Boolean))];
260+
let typ = LogicalType::struct_type(fields);
261+
262+
assert_eq!(typ.num_children(), 1);
263+
assert_eq!(typ.child_name(0), "hello");
264+
assert_eq!(typ.child(0).id(), crate::vtab::LogicalTypeId::Boolean);
265+
}
266+
267+
#[test]
268+
fn test_decimal() {
269+
let typ = LogicalType::decimal(10, 2);
270+
271+
assert_eq!(typ.id(), crate::vtab::LogicalTypeId::Decimal);
272+
assert_eq!(typ.decimal_width(), 10);
273+
assert_eq!(typ.decimal_scale(), 2);
274+
}
275+
276+
#[test]
277+
fn test_decimal_methods() {
278+
let typ = LogicalType::new(crate::vtab::LogicalTypeId::Varchar);
279+
280+
assert_eq!(typ.decimal_width(), 0);
281+
assert_eq!(typ.decimal_scale(), 0);
282+
}
283+
}

0 commit comments

Comments
 (0)