mirror of
https://github.com/nushell/nushell.git
synced 2025-04-24 21:28:20 +02:00
Moving dtype related items to nu_dtype
This commit is contained in:
parent
7d6f8b6640
commit
5d79e816a1
@ -22,7 +22,8 @@ pub use nu_dtype::NuDataType;
|
|||||||
pub use nu_expression::{NuExpression, NuExpressionCustomValue};
|
pub use nu_expression::{NuExpression, NuExpressionCustomValue};
|
||||||
pub use nu_lazyframe::{NuLazyFrame, NuLazyFrameCustomValue};
|
pub use nu_lazyframe::{NuLazyFrame, NuLazyFrameCustomValue};
|
||||||
pub use nu_lazygroupby::{NuLazyGroupBy, NuLazyGroupByCustomValue};
|
pub use nu_lazygroupby::{NuLazyGroupBy, NuLazyGroupByCustomValue};
|
||||||
pub use nu_schema::{str_to_dtype, NuSchema};
|
pub use nu_schema::NuSchema;
|
||||||
|
pub use nu_dtype::str_to_dtype;
|
||||||
pub use nu_when::{NuWhen, NuWhenCustomValue, NuWhenType};
|
pub use nu_when::{NuWhen, NuWhenCustomValue, NuWhenType};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
@ -389,3 +390,199 @@ pub trait CustomValueSupport: Cacheable {
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use polars::prelude::{DataType, TimeUnit, UnknownKind};
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_dtype_str_to_schema_simple_types() {
|
||||||
|
let dtype = "bool";
|
||||||
|
let schema = str_to_dtype(dtype, Span::unknown()).unwrap();
|
||||||
|
let expected = DataType::Boolean;
|
||||||
|
assert_eq!(schema, expected);
|
||||||
|
|
||||||
|
let dtype = "u8";
|
||||||
|
let schema = str_to_dtype(dtype, Span::unknown()).unwrap();
|
||||||
|
let expected = DataType::UInt8;
|
||||||
|
assert_eq!(schema, expected);
|
||||||
|
|
||||||
|
let dtype = "u16";
|
||||||
|
let schema = str_to_dtype(dtype, Span::unknown()).unwrap();
|
||||||
|
let expected = DataType::UInt16;
|
||||||
|
assert_eq!(schema, expected);
|
||||||
|
|
||||||
|
let dtype = "u32";
|
||||||
|
let schema = str_to_dtype(dtype, Span::unknown()).unwrap();
|
||||||
|
let expected = DataType::UInt32;
|
||||||
|
assert_eq!(schema, expected);
|
||||||
|
|
||||||
|
let dtype = "u64";
|
||||||
|
let schema = str_to_dtype(dtype, Span::unknown()).unwrap();
|
||||||
|
let expected = DataType::UInt64;
|
||||||
|
assert_eq!(schema, expected);
|
||||||
|
|
||||||
|
let dtype = "i8";
|
||||||
|
let schema = str_to_dtype(dtype, Span::unknown()).unwrap();
|
||||||
|
let expected = DataType::Int8;
|
||||||
|
assert_eq!(schema, expected);
|
||||||
|
|
||||||
|
let dtype = "i16";
|
||||||
|
let schema = str_to_dtype(dtype, Span::unknown()).unwrap();
|
||||||
|
let expected = DataType::Int16;
|
||||||
|
assert_eq!(schema, expected);
|
||||||
|
|
||||||
|
let dtype = "i32";
|
||||||
|
let schema = str_to_dtype(dtype, Span::unknown()).unwrap();
|
||||||
|
let expected = DataType::Int32;
|
||||||
|
assert_eq!(schema, expected);
|
||||||
|
|
||||||
|
let dtype = "i64";
|
||||||
|
let schema = str_to_dtype(dtype, Span::unknown()).unwrap();
|
||||||
|
let expected = DataType::Int64;
|
||||||
|
assert_eq!(schema, expected);
|
||||||
|
|
||||||
|
let dtype = "str";
|
||||||
|
let schema = str_to_dtype(dtype, Span::unknown()).unwrap();
|
||||||
|
let expected = DataType::String;
|
||||||
|
assert_eq!(schema, expected);
|
||||||
|
|
||||||
|
let dtype = "binary";
|
||||||
|
let schema = str_to_dtype(dtype, Span::unknown()).unwrap();
|
||||||
|
let expected = DataType::Binary;
|
||||||
|
assert_eq!(schema, expected);
|
||||||
|
|
||||||
|
let dtype = "date";
|
||||||
|
let schema = str_to_dtype(dtype, Span::unknown()).unwrap();
|
||||||
|
let expected = DataType::Date;
|
||||||
|
assert_eq!(schema, expected);
|
||||||
|
|
||||||
|
let dtype = "time";
|
||||||
|
let schema = str_to_dtype(dtype, Span::unknown()).unwrap();
|
||||||
|
let expected = DataType::Time;
|
||||||
|
assert_eq!(schema, expected);
|
||||||
|
|
||||||
|
let dtype = "null";
|
||||||
|
let schema = str_to_dtype(dtype, Span::unknown()).unwrap();
|
||||||
|
let expected = DataType::Null;
|
||||||
|
assert_eq!(schema, expected);
|
||||||
|
|
||||||
|
let dtype = "unknown";
|
||||||
|
let schema = str_to_dtype(dtype, Span::unknown()).unwrap();
|
||||||
|
let expected = DataType::Unknown(UnknownKind::Any);
|
||||||
|
assert_eq!(schema, expected);
|
||||||
|
|
||||||
|
let dtype = "object";
|
||||||
|
let schema = str_to_dtype(dtype, Span::unknown()).unwrap();
|
||||||
|
let expected = DataType::Object("unknown", None);
|
||||||
|
assert_eq!(schema, expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_dtype_str_schema_datetime() {
|
||||||
|
let dtype = "datetime<ms, *>";
|
||||||
|
let schema = str_to_dtype(dtype, Span::unknown()).unwrap();
|
||||||
|
let expected = DataType::Datetime(TimeUnit::Milliseconds, None);
|
||||||
|
assert_eq!(schema, expected);
|
||||||
|
|
||||||
|
let dtype = "datetime<us, *>";
|
||||||
|
let schema = str_to_dtype(dtype, Span::unknown()).unwrap();
|
||||||
|
let expected = DataType::Datetime(TimeUnit::Microseconds, None);
|
||||||
|
assert_eq!(schema, expected);
|
||||||
|
|
||||||
|
let dtype = "datetime<μs, *>";
|
||||||
|
let schema = str_to_dtype(dtype, Span::unknown()).unwrap();
|
||||||
|
let expected = DataType::Datetime(TimeUnit::Microseconds, None);
|
||||||
|
assert_eq!(schema, expected);
|
||||||
|
|
||||||
|
let dtype = "datetime<ns, *>";
|
||||||
|
let schema = str_to_dtype(dtype, Span::unknown()).unwrap();
|
||||||
|
let expected = DataType::Datetime(TimeUnit::Nanoseconds, None);
|
||||||
|
assert_eq!(schema, expected);
|
||||||
|
|
||||||
|
let dtype = "datetime<ms, UTC>";
|
||||||
|
let schema = str_to_dtype(dtype, Span::unknown()).unwrap();
|
||||||
|
let expected = DataType::Datetime(TimeUnit::Milliseconds, Some("UTC".into()));
|
||||||
|
assert_eq!(schema, expected);
|
||||||
|
|
||||||
|
let dtype = "invalid";
|
||||||
|
let schema = str_to_dtype(dtype, Span::unknown());
|
||||||
|
assert!(schema.is_err())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_dtype_str_schema_duration() {
|
||||||
|
let dtype = "duration<ms>";
|
||||||
|
let schema = str_to_dtype(dtype, Span::unknown()).unwrap();
|
||||||
|
let expected = DataType::Duration(TimeUnit::Milliseconds);
|
||||||
|
assert_eq!(schema, expected);
|
||||||
|
|
||||||
|
let dtype = "duration<us>";
|
||||||
|
let schema = str_to_dtype(dtype, Span::unknown()).unwrap();
|
||||||
|
let expected = DataType::Duration(TimeUnit::Microseconds);
|
||||||
|
assert_eq!(schema, expected);
|
||||||
|
|
||||||
|
let dtype = "duration<μs>";
|
||||||
|
let schema = str_to_dtype(dtype, Span::unknown()).unwrap();
|
||||||
|
let expected = DataType::Duration(TimeUnit::Microseconds);
|
||||||
|
assert_eq!(schema, expected);
|
||||||
|
|
||||||
|
let dtype = "duration<ns>";
|
||||||
|
let schema = str_to_dtype(dtype, Span::unknown()).unwrap();
|
||||||
|
let expected = DataType::Duration(TimeUnit::Nanoseconds);
|
||||||
|
assert_eq!(schema, expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_dtype_str_schema_decimal() {
|
||||||
|
let dtype = "decimal<7,2>";
|
||||||
|
let schema = str_to_dtype(dtype, Span::unknown()).unwrap();
|
||||||
|
let expected = DataType::Decimal(Some(7usize), Some(2usize));
|
||||||
|
assert_eq!(schema, expected);
|
||||||
|
|
||||||
|
// "*" is not a permitted value for scale
|
||||||
|
let dtype = "decimal<7,*>";
|
||||||
|
let schema = str_to_dtype(dtype, Span::unknown());
|
||||||
|
assert!(matches!(schema, Err(ShellError::GenericError { .. })));
|
||||||
|
|
||||||
|
let dtype = "decimal<*,2>";
|
||||||
|
let schema = str_to_dtype(dtype, Span::unknown()).unwrap();
|
||||||
|
let expected = DataType::Decimal(None, Some(2usize));
|
||||||
|
assert_eq!(schema, expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_dtype_str_to_schema_list_types() {
|
||||||
|
let dtype = "list<i32>";
|
||||||
|
let schema = str_to_dtype(dtype, Span::unknown()).unwrap();
|
||||||
|
let expected = DataType::List(Box::new(DataType::Int32));
|
||||||
|
assert_eq!(schema, expected);
|
||||||
|
|
||||||
|
let dtype = "list<duration<ms>>";
|
||||||
|
let schema = str_to_dtype(dtype, Span::unknown()).unwrap();
|
||||||
|
let expected = DataType::List(Box::new(DataType::Duration(TimeUnit::Milliseconds)));
|
||||||
|
assert_eq!(schema, expected);
|
||||||
|
|
||||||
|
let dtype = "list<datetime<ms, *>>";
|
||||||
|
let schema = str_to_dtype(dtype, Span::unknown()).unwrap();
|
||||||
|
let expected = DataType::List(Box::new(DataType::Datetime(TimeUnit::Milliseconds, None)));
|
||||||
|
assert_eq!(schema, expected);
|
||||||
|
|
||||||
|
let dtype = "list<decimal<7,2>>";
|
||||||
|
let schema = str_to_dtype(dtype, Span::unknown()).unwrap();
|
||||||
|
let expected = DataType::List(Box::new(DataType::Decimal(Some(7usize), Some(2usize))));
|
||||||
|
assert_eq!(schema, expected);
|
||||||
|
|
||||||
|
let dtype = "list<decimal<*,2>>";
|
||||||
|
let schema = str_to_dtype(dtype, Span::unknown()).unwrap();
|
||||||
|
let expected = DataType::List(Box::new(DataType::Decimal(None, Some(2usize))));
|
||||||
|
assert_eq!(schema, expected);
|
||||||
|
|
||||||
|
let dtype = "list<decimal<7,*>>";
|
||||||
|
let schema = str_to_dtype(dtype, Span::unknown());
|
||||||
|
assert!(matches!(schema, Err(ShellError::GenericError { .. })));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -2,13 +2,13 @@ mod custom_value;
|
|||||||
|
|
||||||
use custom_value::NuDataTypeCustomValue;
|
use custom_value::NuDataTypeCustomValue;
|
||||||
use nu_protocol::{ShellError, Span, Value};
|
use nu_protocol::{ShellError, Span, Value};
|
||||||
use polars::prelude::DataType;
|
use polars::prelude::{DataType, PlSmallStr, TimeUnit, UnknownKind};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use crate::Cacheable;
|
use crate::Cacheable;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
nu_schema::dtype_to_value, str_to_dtype, CustomValueSupport, PolarsPluginObject,
|
nu_schema::dtype_to_value, CustomValueSupport, PolarsPluginObject,
|
||||||
PolarsPluginType,
|
PolarsPluginType,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -106,3 +106,172 @@ impl CustomValueSupport for NuDataType {
|
|||||||
Ok(dtype_to_value(&self.dtype, span))
|
Ok(dtype_to_value(&self.dtype, span))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn str_to_dtype(dtype: &str, span: Span) -> Result<DataType, ShellError> {
|
||||||
|
match dtype {
|
||||||
|
"bool" => Ok(DataType::Boolean),
|
||||||
|
"u8" => Ok(DataType::UInt8),
|
||||||
|
"u16" => Ok(DataType::UInt16),
|
||||||
|
"u32" => Ok(DataType::UInt32),
|
||||||
|
"u64" => Ok(DataType::UInt64),
|
||||||
|
"i8" => Ok(DataType::Int8),
|
||||||
|
"i16" => Ok(DataType::Int16),
|
||||||
|
"i32" => Ok(DataType::Int32),
|
||||||
|
"i64" => Ok(DataType::Int64),
|
||||||
|
"f32" => Ok(DataType::Float32),
|
||||||
|
"f64" => Ok(DataType::Float64),
|
||||||
|
"str" => Ok(DataType::String),
|
||||||
|
"binary" => Ok(DataType::Binary),
|
||||||
|
"date" => Ok(DataType::Date),
|
||||||
|
"time" => Ok(DataType::Time),
|
||||||
|
"null" => Ok(DataType::Null),
|
||||||
|
"unknown" => Ok(DataType::Unknown(UnknownKind::Any)),
|
||||||
|
"object" => Ok(DataType::Object("unknown", None)),
|
||||||
|
_ if dtype.starts_with("list") => {
|
||||||
|
let dtype = dtype
|
||||||
|
.trim_start_matches("list")
|
||||||
|
.trim_start_matches('<')
|
||||||
|
.trim_end_matches('>')
|
||||||
|
.trim();
|
||||||
|
let dtype = str_to_dtype(dtype, span)?;
|
||||||
|
Ok(DataType::List(Box::new(dtype)))
|
||||||
|
}
|
||||||
|
_ if dtype.starts_with("datetime") => {
|
||||||
|
let dtype = dtype
|
||||||
|
.trim_start_matches("datetime")
|
||||||
|
.trim_start_matches('<')
|
||||||
|
.trim_end_matches('>');
|
||||||
|
let mut split = dtype.split(',');
|
||||||
|
let next = split
|
||||||
|
.next()
|
||||||
|
.ok_or_else(|| ShellError::GenericError {
|
||||||
|
error: "Invalid polars data type".into(),
|
||||||
|
msg: "Missing time unit".into(),
|
||||||
|
span: Some(span),
|
||||||
|
help: None,
|
||||||
|
inner: vec![],
|
||||||
|
})?
|
||||||
|
.trim();
|
||||||
|
let time_unit = str_to_time_unit(next, span)?;
|
||||||
|
let next = split
|
||||||
|
.next()
|
||||||
|
.ok_or_else(|| ShellError::GenericError {
|
||||||
|
error: "Invalid polars data type".into(),
|
||||||
|
msg: "Missing time zone".into(),
|
||||||
|
span: Some(span),
|
||||||
|
help: None,
|
||||||
|
inner: vec![],
|
||||||
|
})?
|
||||||
|
.trim();
|
||||||
|
let timezone = if "*" == next {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(next.to_string())
|
||||||
|
};
|
||||||
|
Ok(DataType::Datetime(
|
||||||
|
time_unit,
|
||||||
|
timezone.map(PlSmallStr::from),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
_ if dtype.starts_with("duration") => {
|
||||||
|
let inner = dtype.trim_start_matches("duration<").trim_end_matches('>');
|
||||||
|
let next = inner
|
||||||
|
.split(',')
|
||||||
|
.next()
|
||||||
|
.ok_or_else(|| ShellError::GenericError {
|
||||||
|
error: "Invalid polars data type".into(),
|
||||||
|
msg: "Missing time unit".into(),
|
||||||
|
span: Some(span),
|
||||||
|
help: None,
|
||||||
|
inner: vec![],
|
||||||
|
})?
|
||||||
|
.trim();
|
||||||
|
let time_unit = str_to_time_unit(next, span)?;
|
||||||
|
Ok(DataType::Duration(time_unit))
|
||||||
|
}
|
||||||
|
_ if dtype.starts_with("decimal") => {
|
||||||
|
let dtype = dtype
|
||||||
|
.trim_start_matches("decimal")
|
||||||
|
.trim_start_matches('<')
|
||||||
|
.trim_end_matches('>');
|
||||||
|
let mut split = dtype.split(',');
|
||||||
|
let next = split
|
||||||
|
.next()
|
||||||
|
.ok_or_else(|| ShellError::GenericError {
|
||||||
|
error: "Invalid polars data type".into(),
|
||||||
|
msg: "Missing decimal precision".into(),
|
||||||
|
span: Some(span),
|
||||||
|
help: None,
|
||||||
|
inner: vec![],
|
||||||
|
})?
|
||||||
|
.trim();
|
||||||
|
let precision = match next {
|
||||||
|
"*" => None, // infer
|
||||||
|
_ => Some(
|
||||||
|
next.parse::<usize>()
|
||||||
|
.map_err(|e| ShellError::GenericError {
|
||||||
|
error: "Invalid polars data type".into(),
|
||||||
|
msg: format!("Error in parsing decimal precision: {e}"),
|
||||||
|
span: Some(span),
|
||||||
|
help: None,
|
||||||
|
inner: vec![],
|
||||||
|
})?,
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
let next = split
|
||||||
|
.next()
|
||||||
|
.ok_or_else(|| ShellError::GenericError {
|
||||||
|
error: "Invalid polars data type".into(),
|
||||||
|
msg: "Missing decimal scale".into(),
|
||||||
|
span: Some(span),
|
||||||
|
help: None,
|
||||||
|
inner: vec![],
|
||||||
|
})?
|
||||||
|
.trim();
|
||||||
|
let scale = match next {
|
||||||
|
"*" => Err(ShellError::GenericError {
|
||||||
|
error: "Invalid polars data type".into(),
|
||||||
|
msg: "`*` is not a permitted value for scale".into(),
|
||||||
|
span: Some(span),
|
||||||
|
help: None,
|
||||||
|
inner: vec![],
|
||||||
|
}),
|
||||||
|
_ => next
|
||||||
|
.parse::<usize>()
|
||||||
|
.map(Some)
|
||||||
|
.map_err(|e| ShellError::GenericError {
|
||||||
|
error: "Invalid polars data type".into(),
|
||||||
|
msg: format!("Error in parsing decimal precision: {e}"),
|
||||||
|
span: Some(span),
|
||||||
|
help: None,
|
||||||
|
inner: vec![],
|
||||||
|
}),
|
||||||
|
}?;
|
||||||
|
Ok(DataType::Decimal(precision, scale))
|
||||||
|
}
|
||||||
|
_ => Err(ShellError::GenericError {
|
||||||
|
error: "Invalid polars data type".into(),
|
||||||
|
msg: format!("Unknown type: {dtype}"),
|
||||||
|
span: Some(span),
|
||||||
|
help: None,
|
||||||
|
inner: vec![],
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn str_to_time_unit(ts_string: &str, span: Span) -> Result<TimeUnit, ShellError> {
|
||||||
|
match ts_string {
|
||||||
|
"ms" => Ok(TimeUnit::Milliseconds),
|
||||||
|
"us" | "μs" => Ok(TimeUnit::Microseconds),
|
||||||
|
"ns" => Ok(TimeUnit::Nanoseconds),
|
||||||
|
_ => Err(ShellError::GenericError {
|
||||||
|
error: "Invalid polars data type".into(),
|
||||||
|
msg: "Invalid time unit".into(),
|
||||||
|
span: Some(span),
|
||||||
|
help: None,
|
||||||
|
inner: vec![],
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use nu_protocol::{ShellError, Span, Value};
|
use nu_protocol::{ShellError, Span, Value};
|
||||||
use polars::{
|
use polars::prelude::{DataType, Field, Schema, SchemaExt, SchemaRef};
|
||||||
datatypes::UnknownKind,
|
|
||||||
prelude::{DataType, Field, PlSmallStr, Schema, SchemaExt, SchemaRef, TimeUnit},
|
use super::str_to_dtype;
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct NuSchema {
|
pub struct NuSchema {
|
||||||
@ -87,174 +86,6 @@ fn value_to_fields(value: &Value, span: Span) -> Result<Vec<Field>, ShellError>
|
|||||||
Ok(fields)
|
Ok(fields)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn str_to_dtype(dtype: &str, span: Span) -> Result<DataType, ShellError> {
|
|
||||||
match dtype {
|
|
||||||
"bool" => Ok(DataType::Boolean),
|
|
||||||
"u8" => Ok(DataType::UInt8),
|
|
||||||
"u16" => Ok(DataType::UInt16),
|
|
||||||
"u32" => Ok(DataType::UInt32),
|
|
||||||
"u64" => Ok(DataType::UInt64),
|
|
||||||
"i8" => Ok(DataType::Int8),
|
|
||||||
"i16" => Ok(DataType::Int16),
|
|
||||||
"i32" => Ok(DataType::Int32),
|
|
||||||
"i64" => Ok(DataType::Int64),
|
|
||||||
"f32" => Ok(DataType::Float32),
|
|
||||||
"f64" => Ok(DataType::Float64),
|
|
||||||
"str" => Ok(DataType::String),
|
|
||||||
"binary" => Ok(DataType::Binary),
|
|
||||||
"date" => Ok(DataType::Date),
|
|
||||||
"time" => Ok(DataType::Time),
|
|
||||||
"null" => Ok(DataType::Null),
|
|
||||||
"unknown" => Ok(DataType::Unknown(UnknownKind::Any)),
|
|
||||||
"object" => Ok(DataType::Object("unknown", None)),
|
|
||||||
_ if dtype.starts_with("list") => {
|
|
||||||
let dtype = dtype
|
|
||||||
.trim_start_matches("list")
|
|
||||||
.trim_start_matches('<')
|
|
||||||
.trim_end_matches('>')
|
|
||||||
.trim();
|
|
||||||
let dtype = str_to_dtype(dtype, span)?;
|
|
||||||
Ok(DataType::List(Box::new(dtype)))
|
|
||||||
}
|
|
||||||
_ if dtype.starts_with("datetime") => {
|
|
||||||
let dtype = dtype
|
|
||||||
.trim_start_matches("datetime")
|
|
||||||
.trim_start_matches('<')
|
|
||||||
.trim_end_matches('>');
|
|
||||||
let mut split = dtype.split(',');
|
|
||||||
let next = split
|
|
||||||
.next()
|
|
||||||
.ok_or_else(|| ShellError::GenericError {
|
|
||||||
error: "Invalid polars data type".into(),
|
|
||||||
msg: "Missing time unit".into(),
|
|
||||||
span: Some(span),
|
|
||||||
help: None,
|
|
||||||
inner: vec![],
|
|
||||||
})?
|
|
||||||
.trim();
|
|
||||||
let time_unit = str_to_time_unit(next, span)?;
|
|
||||||
let next = split
|
|
||||||
.next()
|
|
||||||
.ok_or_else(|| ShellError::GenericError {
|
|
||||||
error: "Invalid polars data type".into(),
|
|
||||||
msg: "Missing time zone".into(),
|
|
||||||
span: Some(span),
|
|
||||||
help: None,
|
|
||||||
inner: vec![],
|
|
||||||
})?
|
|
||||||
.trim();
|
|
||||||
let timezone = if "*" == next {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(next.to_string())
|
|
||||||
};
|
|
||||||
Ok(DataType::Datetime(
|
|
||||||
time_unit,
|
|
||||||
timezone.map(PlSmallStr::from),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
_ if dtype.starts_with("duration") => {
|
|
||||||
let inner = dtype.trim_start_matches("duration<").trim_end_matches('>');
|
|
||||||
let next = inner
|
|
||||||
.split(',')
|
|
||||||
.next()
|
|
||||||
.ok_or_else(|| ShellError::GenericError {
|
|
||||||
error: "Invalid polars data type".into(),
|
|
||||||
msg: "Missing time unit".into(),
|
|
||||||
span: Some(span),
|
|
||||||
help: None,
|
|
||||||
inner: vec![],
|
|
||||||
})?
|
|
||||||
.trim();
|
|
||||||
let time_unit = str_to_time_unit(next, span)?;
|
|
||||||
Ok(DataType::Duration(time_unit))
|
|
||||||
}
|
|
||||||
_ if dtype.starts_with("decimal") => {
|
|
||||||
let dtype = dtype
|
|
||||||
.trim_start_matches("decimal")
|
|
||||||
.trim_start_matches('<')
|
|
||||||
.trim_end_matches('>');
|
|
||||||
let mut split = dtype.split(',');
|
|
||||||
let next = split
|
|
||||||
.next()
|
|
||||||
.ok_or_else(|| ShellError::GenericError {
|
|
||||||
error: "Invalid polars data type".into(),
|
|
||||||
msg: "Missing decimal precision".into(),
|
|
||||||
span: Some(span),
|
|
||||||
help: None,
|
|
||||||
inner: vec![],
|
|
||||||
})?
|
|
||||||
.trim();
|
|
||||||
let precision = match next {
|
|
||||||
"*" => None, // infer
|
|
||||||
_ => Some(
|
|
||||||
next.parse::<usize>()
|
|
||||||
.map_err(|e| ShellError::GenericError {
|
|
||||||
error: "Invalid polars data type".into(),
|
|
||||||
msg: format!("Error in parsing decimal precision: {e}"),
|
|
||||||
span: Some(span),
|
|
||||||
help: None,
|
|
||||||
inner: vec![],
|
|
||||||
})?,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
|
|
||||||
let next = split
|
|
||||||
.next()
|
|
||||||
.ok_or_else(|| ShellError::GenericError {
|
|
||||||
error: "Invalid polars data type".into(),
|
|
||||||
msg: "Missing decimal scale".into(),
|
|
||||||
span: Some(span),
|
|
||||||
help: None,
|
|
||||||
inner: vec![],
|
|
||||||
})?
|
|
||||||
.trim();
|
|
||||||
let scale = match next {
|
|
||||||
"*" => Err(ShellError::GenericError {
|
|
||||||
error: "Invalid polars data type".into(),
|
|
||||||
msg: "`*` is not a permitted value for scale".into(),
|
|
||||||
span: Some(span),
|
|
||||||
help: None,
|
|
||||||
inner: vec![],
|
|
||||||
}),
|
|
||||||
_ => next
|
|
||||||
.parse::<usize>()
|
|
||||||
.map(Some)
|
|
||||||
.map_err(|e| ShellError::GenericError {
|
|
||||||
error: "Invalid polars data type".into(),
|
|
||||||
msg: format!("Error in parsing decimal precision: {e}"),
|
|
||||||
span: Some(span),
|
|
||||||
help: None,
|
|
||||||
inner: vec![],
|
|
||||||
}),
|
|
||||||
}?;
|
|
||||||
Ok(DataType::Decimal(precision, scale))
|
|
||||||
}
|
|
||||||
_ => Err(ShellError::GenericError {
|
|
||||||
error: "Invalid polars data type".into(),
|
|
||||||
msg: format!("Unknown type: {dtype}"),
|
|
||||||
span: Some(span),
|
|
||||||
help: None,
|
|
||||||
inner: vec![],
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn str_to_time_unit(ts_string: &str, span: Span) -> Result<TimeUnit, ShellError> {
|
|
||||||
match ts_string {
|
|
||||||
"ms" => Ok(TimeUnit::Milliseconds),
|
|
||||||
"us" | "μs" => Ok(TimeUnit::Microseconds),
|
|
||||||
"ns" => Ok(TimeUnit::Nanoseconds),
|
|
||||||
_ => Err(ShellError::GenericError {
|
|
||||||
error: "Invalid polars data type".into(),
|
|
||||||
msg: "Invalid time unit".into(),
|
|
||||||
span: Some(span),
|
|
||||||
help: None,
|
|
||||||
inner: vec![],
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
|
|
||||||
@ -289,192 +120,4 @@ mod test {
|
|||||||
]);
|
]);
|
||||||
assert_eq!(schema, expected);
|
assert_eq!(schema, expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_dtype_str_to_schema_simple_types() {
|
|
||||||
let dtype = "bool";
|
|
||||||
let schema = str_to_dtype(dtype, Span::unknown()).unwrap();
|
|
||||||
let expected = DataType::Boolean;
|
|
||||||
assert_eq!(schema, expected);
|
|
||||||
|
|
||||||
let dtype = "u8";
|
|
||||||
let schema = str_to_dtype(dtype, Span::unknown()).unwrap();
|
|
||||||
let expected = DataType::UInt8;
|
|
||||||
assert_eq!(schema, expected);
|
|
||||||
|
|
||||||
let dtype = "u16";
|
|
||||||
let schema = str_to_dtype(dtype, Span::unknown()).unwrap();
|
|
||||||
let expected = DataType::UInt16;
|
|
||||||
assert_eq!(schema, expected);
|
|
||||||
|
|
||||||
let dtype = "u32";
|
|
||||||
let schema = str_to_dtype(dtype, Span::unknown()).unwrap();
|
|
||||||
let expected = DataType::UInt32;
|
|
||||||
assert_eq!(schema, expected);
|
|
||||||
|
|
||||||
let dtype = "u64";
|
|
||||||
let schema = str_to_dtype(dtype, Span::unknown()).unwrap();
|
|
||||||
let expected = DataType::UInt64;
|
|
||||||
assert_eq!(schema, expected);
|
|
||||||
|
|
||||||
let dtype = "i8";
|
|
||||||
let schema = str_to_dtype(dtype, Span::unknown()).unwrap();
|
|
||||||
let expected = DataType::Int8;
|
|
||||||
assert_eq!(schema, expected);
|
|
||||||
|
|
||||||
let dtype = "i16";
|
|
||||||
let schema = str_to_dtype(dtype, Span::unknown()).unwrap();
|
|
||||||
let expected = DataType::Int16;
|
|
||||||
assert_eq!(schema, expected);
|
|
||||||
|
|
||||||
let dtype = "i32";
|
|
||||||
let schema = str_to_dtype(dtype, Span::unknown()).unwrap();
|
|
||||||
let expected = DataType::Int32;
|
|
||||||
assert_eq!(schema, expected);
|
|
||||||
|
|
||||||
let dtype = "i64";
|
|
||||||
let schema = str_to_dtype(dtype, Span::unknown()).unwrap();
|
|
||||||
let expected = DataType::Int64;
|
|
||||||
assert_eq!(schema, expected);
|
|
||||||
|
|
||||||
let dtype = "str";
|
|
||||||
let schema = str_to_dtype(dtype, Span::unknown()).unwrap();
|
|
||||||
let expected = DataType::String;
|
|
||||||
assert_eq!(schema, expected);
|
|
||||||
|
|
||||||
let dtype = "binary";
|
|
||||||
let schema = str_to_dtype(dtype, Span::unknown()).unwrap();
|
|
||||||
let expected = DataType::Binary;
|
|
||||||
assert_eq!(schema, expected);
|
|
||||||
|
|
||||||
let dtype = "date";
|
|
||||||
let schema = str_to_dtype(dtype, Span::unknown()).unwrap();
|
|
||||||
let expected = DataType::Date;
|
|
||||||
assert_eq!(schema, expected);
|
|
||||||
|
|
||||||
let dtype = "time";
|
|
||||||
let schema = str_to_dtype(dtype, Span::unknown()).unwrap();
|
|
||||||
let expected = DataType::Time;
|
|
||||||
assert_eq!(schema, expected);
|
|
||||||
|
|
||||||
let dtype = "null";
|
|
||||||
let schema = str_to_dtype(dtype, Span::unknown()).unwrap();
|
|
||||||
let expected = DataType::Null;
|
|
||||||
assert_eq!(schema, expected);
|
|
||||||
|
|
||||||
let dtype = "unknown";
|
|
||||||
let schema = str_to_dtype(dtype, Span::unknown()).unwrap();
|
|
||||||
let expected = DataType::Unknown(UnknownKind::Any);
|
|
||||||
assert_eq!(schema, expected);
|
|
||||||
|
|
||||||
let dtype = "object";
|
|
||||||
let schema = str_to_dtype(dtype, Span::unknown()).unwrap();
|
|
||||||
let expected = DataType::Object("unknown", None);
|
|
||||||
assert_eq!(schema, expected);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_dtype_str_schema_datetime() {
|
|
||||||
let dtype = "datetime<ms, *>";
|
|
||||||
let schema = str_to_dtype(dtype, Span::unknown()).unwrap();
|
|
||||||
let expected = DataType::Datetime(TimeUnit::Milliseconds, None);
|
|
||||||
assert_eq!(schema, expected);
|
|
||||||
|
|
||||||
let dtype = "datetime<us, *>";
|
|
||||||
let schema = str_to_dtype(dtype, Span::unknown()).unwrap();
|
|
||||||
let expected = DataType::Datetime(TimeUnit::Microseconds, None);
|
|
||||||
assert_eq!(schema, expected);
|
|
||||||
|
|
||||||
let dtype = "datetime<μs, *>";
|
|
||||||
let schema = str_to_dtype(dtype, Span::unknown()).unwrap();
|
|
||||||
let expected = DataType::Datetime(TimeUnit::Microseconds, None);
|
|
||||||
assert_eq!(schema, expected);
|
|
||||||
|
|
||||||
let dtype = "datetime<ns, *>";
|
|
||||||
let schema = str_to_dtype(dtype, Span::unknown()).unwrap();
|
|
||||||
let expected = DataType::Datetime(TimeUnit::Nanoseconds, None);
|
|
||||||
assert_eq!(schema, expected);
|
|
||||||
|
|
||||||
let dtype = "datetime<ms, UTC>";
|
|
||||||
let schema = str_to_dtype(dtype, Span::unknown()).unwrap();
|
|
||||||
let expected = DataType::Datetime(TimeUnit::Milliseconds, Some("UTC".into()));
|
|
||||||
assert_eq!(schema, expected);
|
|
||||||
|
|
||||||
let dtype = "invalid";
|
|
||||||
let schema = str_to_dtype(dtype, Span::unknown());
|
|
||||||
assert!(schema.is_err())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_dtype_str_schema_duration() {
|
|
||||||
let dtype = "duration<ms>";
|
|
||||||
let schema = str_to_dtype(dtype, Span::unknown()).unwrap();
|
|
||||||
let expected = DataType::Duration(TimeUnit::Milliseconds);
|
|
||||||
assert_eq!(schema, expected);
|
|
||||||
|
|
||||||
let dtype = "duration<us>";
|
|
||||||
let schema = str_to_dtype(dtype, Span::unknown()).unwrap();
|
|
||||||
let expected = DataType::Duration(TimeUnit::Microseconds);
|
|
||||||
assert_eq!(schema, expected);
|
|
||||||
|
|
||||||
let dtype = "duration<μs>";
|
|
||||||
let schema = str_to_dtype(dtype, Span::unknown()).unwrap();
|
|
||||||
let expected = DataType::Duration(TimeUnit::Microseconds);
|
|
||||||
assert_eq!(schema, expected);
|
|
||||||
|
|
||||||
let dtype = "duration<ns>";
|
|
||||||
let schema = str_to_dtype(dtype, Span::unknown()).unwrap();
|
|
||||||
let expected = DataType::Duration(TimeUnit::Nanoseconds);
|
|
||||||
assert_eq!(schema, expected);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_dtype_str_schema_decimal() {
|
|
||||||
let dtype = "decimal<7,2>";
|
|
||||||
let schema = str_to_dtype(dtype, Span::unknown()).unwrap();
|
|
||||||
let expected = DataType::Decimal(Some(7usize), Some(2usize));
|
|
||||||
assert_eq!(schema, expected);
|
|
||||||
|
|
||||||
// "*" is not a permitted value for scale
|
|
||||||
let dtype = "decimal<7,*>";
|
|
||||||
let schema = str_to_dtype(dtype, Span::unknown());
|
|
||||||
assert!(matches!(schema, Err(ShellError::GenericError { .. })));
|
|
||||||
|
|
||||||
let dtype = "decimal<*,2>";
|
|
||||||
let schema = str_to_dtype(dtype, Span::unknown()).unwrap();
|
|
||||||
let expected = DataType::Decimal(None, Some(2usize));
|
|
||||||
assert_eq!(schema, expected);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_dtype_str_to_schema_list_types() {
|
|
||||||
let dtype = "list<i32>";
|
|
||||||
let schema = str_to_dtype(dtype, Span::unknown()).unwrap();
|
|
||||||
let expected = DataType::List(Box::new(DataType::Int32));
|
|
||||||
assert_eq!(schema, expected);
|
|
||||||
|
|
||||||
let dtype = "list<duration<ms>>";
|
|
||||||
let schema = str_to_dtype(dtype, Span::unknown()).unwrap();
|
|
||||||
let expected = DataType::List(Box::new(DataType::Duration(TimeUnit::Milliseconds)));
|
|
||||||
assert_eq!(schema, expected);
|
|
||||||
|
|
||||||
let dtype = "list<datetime<ms, *>>";
|
|
||||||
let schema = str_to_dtype(dtype, Span::unknown()).unwrap();
|
|
||||||
let expected = DataType::List(Box::new(DataType::Datetime(TimeUnit::Milliseconds, None)));
|
|
||||||
assert_eq!(schema, expected);
|
|
||||||
|
|
||||||
let dtype = "list<decimal<7,2>>";
|
|
||||||
let schema = str_to_dtype(dtype, Span::unknown()).unwrap();
|
|
||||||
let expected = DataType::List(Box::new(DataType::Decimal(Some(7usize), Some(2usize))));
|
|
||||||
assert_eq!(schema, expected);
|
|
||||||
|
|
||||||
let dtype = "list<decimal<*,2>>";
|
|
||||||
let schema = str_to_dtype(dtype, Span::unknown()).unwrap();
|
|
||||||
let expected = DataType::List(Box::new(DataType::Decimal(None, Some(2usize))));
|
|
||||||
assert_eq!(schema, expected);
|
|
||||||
|
|
||||||
let dtype = "list<decimal<7,*>>";
|
|
||||||
let schema = str_to_dtype(dtype, Span::unknown());
|
|
||||||
assert!(matches!(schema, Err(ShellError::GenericError { .. })));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user