datafusion_python/expr/
literal.rs1use crate::errors::PyDataFusionError;
19use datafusion::{common::ScalarValue, logical_expr::expr::FieldMetadata};
20use pyo3::{prelude::*, IntoPyObjectExt};
21
22#[pyclass(name = "Literal", module = "datafusion.expr", subclass)]
23#[derive(Clone)]
24pub struct PyLiteral {
25 pub value: ScalarValue,
26 pub metadata: Option<FieldMetadata>,
27}
28
29impl PyLiteral {
30 pub fn new_with_metadata(value: ScalarValue, metadata: Option<FieldMetadata>) -> PyLiteral {
31 Self { value, metadata }
32 }
33}
34
35impl From<PyLiteral> for ScalarValue {
36 fn from(lit: PyLiteral) -> ScalarValue {
37 lit.value
38 }
39}
40
41impl From<ScalarValue> for PyLiteral {
42 fn from(value: ScalarValue) -> PyLiteral {
43 PyLiteral {
44 value,
45 metadata: None,
46 }
47 }
48}
49
50macro_rules! extract_scalar_value {
51 ($self: expr, $variant: ident) => {
52 match &$self.value {
53 ScalarValue::$variant(value) => Ok(*value),
54 other => Err(unexpected_literal_value(other)),
55 }
56 };
57}
58
59#[pymethods]
60impl PyLiteral {
61 fn data_type(&self) -> String {
63 format!("{}", self.value.data_type())
64 }
65
66 pub fn value_f32(&self) -> PyResult<Option<f32>> {
67 extract_scalar_value!(self, Float32)
68 }
69
70 pub fn value_f64(&self) -> PyResult<Option<f64>> {
71 extract_scalar_value!(self, Float64)
72 }
73
74 pub fn value_decimal128(&mut self) -> PyResult<(Option<i128>, u8, i8)> {
75 match &self.value {
76 ScalarValue::Decimal128(value, precision, scale) => Ok((*value, *precision, *scale)),
77 other => Err(unexpected_literal_value(other)),
78 }
79 }
80
81 pub fn value_i8(&self) -> PyResult<Option<i8>> {
82 extract_scalar_value!(self, Int8)
83 }
84
85 pub fn value_i16(&self) -> PyResult<Option<i16>> {
86 extract_scalar_value!(self, Int16)
87 }
88
89 pub fn value_i32(&self) -> PyResult<Option<i32>> {
90 extract_scalar_value!(self, Int32)
91 }
92
93 pub fn value_i64(&self) -> PyResult<Option<i64>> {
94 extract_scalar_value!(self, Int64)
95 }
96
97 pub fn value_u8(&self) -> PyResult<Option<u8>> {
98 extract_scalar_value!(self, UInt8)
99 }
100
101 pub fn value_u16(&self) -> PyResult<Option<u16>> {
102 extract_scalar_value!(self, UInt16)
103 }
104
105 pub fn value_u32(&self) -> PyResult<Option<u32>> {
106 extract_scalar_value!(self, UInt32)
107 }
108
109 pub fn value_u64(&self) -> PyResult<Option<u64>> {
110 extract_scalar_value!(self, UInt64)
111 }
112
113 pub fn value_date32(&self) -> PyResult<Option<i32>> {
114 extract_scalar_value!(self, Date32)
115 }
116
117 pub fn value_date64(&self) -> PyResult<Option<i64>> {
118 extract_scalar_value!(self, Date64)
119 }
120
121 pub fn value_time64(&self) -> PyResult<Option<i64>> {
122 extract_scalar_value!(self, Time64Nanosecond)
123 }
124
125 pub fn value_timestamp(&mut self) -> PyResult<(Option<i64>, Option<String>)> {
126 match &self.value {
127 ScalarValue::TimestampNanosecond(iv, tz)
128 | ScalarValue::TimestampMicrosecond(iv, tz)
129 | ScalarValue::TimestampMillisecond(iv, tz)
130 | ScalarValue::TimestampSecond(iv, tz) => {
131 Ok((*iv, tz.as_ref().map(|s| s.as_ref().to_string())))
132 }
133 other => Err(unexpected_literal_value(other)),
134 }
135 }
136
137 pub fn value_bool(&self) -> PyResult<Option<bool>> {
138 extract_scalar_value!(self, Boolean)
139 }
140
141 pub fn value_string(&self) -> PyResult<Option<String>> {
142 match &self.value {
143 ScalarValue::Utf8(value) => Ok(value.clone()),
144 other => Err(unexpected_literal_value(other)),
145 }
146 }
147
148 pub fn value_interval_day_time(&self) -> PyResult<Option<(i32, i32)>> {
149 match &self.value {
150 ScalarValue::IntervalDayTime(Some(iv)) => Ok(Some((iv.days, iv.milliseconds))),
151 ScalarValue::IntervalDayTime(None) => Ok(None),
152 other => Err(unexpected_literal_value(other)),
153 }
154 }
155
156 #[allow(clippy::wrong_self_convention)]
157 fn into_type<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyAny>> {
158 self.clone().into_bound_py_any(py)
159 }
160
161 fn __repr__(&self) -> PyResult<String> {
162 Ok(format!("{}", self.value))
163 }
164}
165
166fn unexpected_literal_value(value: &ScalarValue) -> PyErr {
167 PyDataFusionError::Common(format!("getValue<T>() - Unexpected value: {value}")).into()
168}