This is an automated email from the ASF dual-hosted git repository.

agrove pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-datafusion-python.git


The following commit(s) were added to refs/heads/main by this push:
     new 2bf684e  Expand Rust return type support for Arrow DataTypes in 
ScalarValue (#287)
2bf684e is described below

commit 2bf684e7fe6105ad66260483154b5e944f2c724d
Author: Jeremy Dyer <[email protected]>
AuthorDate: Thu Mar 16 08:54:48 2023 -0400

    Expand Rust return type support for Arrow DataTypes in ScalarValue (#287)
---
 src/errors.rs       |   2 +
 src/expr/literal.rs | 119 +++++++++++++++++++++++++++++++++++++++++++++-------
 2 files changed, 105 insertions(+), 16 deletions(-)

diff --git a/src/errors.rs b/src/errors.rs
index e739fe3..ce6b3c2 100644
--- a/src/errors.rs
+++ b/src/errors.rs
@@ -23,6 +23,8 @@ use datafusion::arrow::error::ArrowError;
 use datafusion::error::DataFusionError as InnerDataFusionError;
 use pyo3::{exceptions::PyException, PyErr};
 
+pub type Result<T> = std::result::Result<T, DataFusionError>;
+
 #[derive(Debug)]
 pub enum DataFusionError {
     ExecutionError(InnerDataFusionError),
diff --git a/src/expr/literal.rs b/src/expr/literal.rs
index 27674ce..b29497e 100644
--- a/src/expr/literal.rs
+++ b/src/expr/literal.rs
@@ -15,7 +15,7 @@
 // specific language governing permissions and limitations
 // under the License.
 
-use crate::errors::py_runtime_err;
+use crate::errors::{py_runtime_err, DataFusionError};
 use datafusion_common::ScalarValue;
 use pyo3::prelude::*;
 
@@ -37,6 +37,15 @@ impl From<ScalarValue> for PyLiteral {
     }
 }
 
+macro_rules! extract_scalar_value {
+    ($self: expr, $variant: ident) => {
+        match &$self.value {
+            ScalarValue::$variant(value) => Ok(*value),
+            other => Err(unexpected_literal_value(other)),
+        }
+    };
+}
+
 #[pymethods]
 impl PyLiteral {
     /// Get the data type of this literal value
@@ -44,31 +53,109 @@ impl PyLiteral {
         format!("{}", self.value.get_datatype())
     }
 
-    fn value_i32(&self) -> PyResult<i32> {
-        if let ScalarValue::Int32(Some(n)) = &self.value {
-            Ok(*n)
-        } else {
-            Err(py_runtime_err("Cannot access value as i32"))
+    pub fn value_f32(&self) -> PyResult<Option<f32>> {
+        extract_scalar_value!(self, Float32)
+    }
+
+    pub fn value_f64(&self) -> PyResult<Option<f64>> {
+        extract_scalar_value!(self, Float64)
+    }
+
+    pub fn value_decimal128(&mut self) -> PyResult<(Option<i128>, u8, i8)> {
+        match &self.value {
+            ScalarValue::Decimal128(value, precision, scale) => Ok((*value, 
*precision, *scale)),
+            other => Err(unexpected_literal_value(other)),
+        }
+    }
+
+    pub fn value_i8(&self) -> PyResult<Option<i8>> {
+        extract_scalar_value!(self, Int8)
+    }
+
+    pub fn value_i16(&self) -> PyResult<Option<i16>> {
+        extract_scalar_value!(self, Int16)
+    }
+
+    pub fn value_i32(&self) -> PyResult<Option<i32>> {
+        extract_scalar_value!(self, Int32)
+    }
+
+    pub fn value_i64(&self) -> PyResult<Option<i64>> {
+        extract_scalar_value!(self, Int64)
+    }
+
+    pub fn value_u8(&self) -> PyResult<Option<u8>> {
+        extract_scalar_value!(self, UInt8)
+    }
+
+    pub fn value_u16(&self) -> PyResult<Option<u16>> {
+        extract_scalar_value!(self, UInt16)
+    }
+
+    pub fn value_u32(&self) -> PyResult<Option<u32>> {
+        extract_scalar_value!(self, UInt32)
+    }
+
+    pub fn value_u64(&self) -> PyResult<Option<u64>> {
+        extract_scalar_value!(self, UInt64)
+    }
+
+    pub fn value_date32(&self) -> PyResult<Option<i32>> {
+        extract_scalar_value!(self, Date32)
+    }
+
+    pub fn value_date64(&self) -> PyResult<Option<i64>> {
+        extract_scalar_value!(self, Date64)
+    }
+
+    pub fn value_time64(&self) -> PyResult<Option<i64>> {
+        extract_scalar_value!(self, Time64Nanosecond)
+    }
+
+    pub fn value_timestamp(&mut self) -> PyResult<(Option<i64>, 
Option<String>)> {
+        match &self.value {
+            ScalarValue::TimestampNanosecond(iv, tz)
+            | ScalarValue::TimestampMicrosecond(iv, tz)
+            | ScalarValue::TimestampMillisecond(iv, tz)
+            | ScalarValue::TimestampSecond(iv, tz) => Ok((*iv, tz.clone())),
+            other => Err(unexpected_literal_value(other)),
         }
     }
 
-    fn value_i64(&self) -> PyResult<i64> {
-        if let ScalarValue::Int64(Some(n)) = &self.value {
-            Ok(*n)
-        } else {
-            Err(py_runtime_err("Cannot access value as i64"))
+    pub fn value_bool(&self) -> PyResult<Option<bool>> {
+        extract_scalar_value!(self, Boolean)
+    }
+
+    pub fn value_string(&self) -> PyResult<Option<String>> {
+        match &self.value {
+            ScalarValue::Utf8(value) => Ok(value.clone()),
+            other => Err(unexpected_literal_value(other)),
         }
     }
 
-    fn value_str(&self) -> PyResult<String> {
-        if let ScalarValue::Utf8(Some(str)) = &self.value {
-            Ok(str.clone())
-        } else {
-            Err(py_runtime_err("Cannot access value as string"))
+    pub fn value_interval_day_time(&self) -> PyResult<Option<(i32, i32)>> {
+        match &self.value {
+            ScalarValue::IntervalDayTime(Some(iv)) => {
+                let interval = *iv as u64;
+                let days = (interval >> 32) as i32;
+                let ms = interval as i32;
+                Ok(Some((days, ms)))
+            }
+            ScalarValue::IntervalDayTime(None) => Ok(None),
+            other => Err(unexpected_literal_value(other)),
         }
     }
 
+    #[allow(clippy::wrong_self_convention)]
+    fn into_type(&self, py: Python) -> PyResult<PyObject> {
+        Ok(self.clone().into_py(py))
+    }
+
     fn __repr__(&self) -> PyResult<String> {
         Ok(format!("{}", self.value))
     }
 }
+
+fn unexpected_literal_value(value: &ScalarValue) -> PyErr {
+    DataFusionError::Common(format!("getValue<T>() - Unexpected value: 
{value}")).into()
+}

Reply via email to