|
1 |
| -use std::{ffi::CString, fmt::Debug}; |
| 1 | +use std::{ |
| 2 | + ffi::{c_char, CString}, |
| 3 | + fmt::Debug, |
| 4 | +}; |
2 | 5 |
|
3 | 6 | use crate::ffi::*;
|
4 | 7 |
|
@@ -176,25 +179,43 @@ impl LogicalType {
|
176 | 179 | }
|
177 | 180 | }
|
178 | 181 |
|
| 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 | + |
179 | 203 | /// 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 | + } |
198 | 219 |
|
199 | 220 | /// Logical type ID
|
200 | 221 | pub fn id(&self) -> LogicalTypeId {
|
@@ -228,3 +249,35 @@ impl LogicalType {
|
228 | 249 | Self::from(c_logical_type)
|
229 | 250 | }
|
230 | 251 | }
|
| 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