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