15
15
// specific language governing permissions and limitations
16
16
// under the License.
17
17
18
- use crate :: errors:: py_runtime_err;
18
+ use crate :: errors:: { py_runtime_err, DataFusionError } ;
19
19
use datafusion_common:: ScalarValue ;
20
20
use pyo3:: prelude:: * ;
21
21
@@ -37,38 +37,125 @@ impl From<ScalarValue> for PyLiteral {
37
37
}
38
38
}
39
39
40
+ macro_rules! extract_scalar_value {
41
+ ( $self: expr, $variant: ident) => {
42
+ match & $self. value {
43
+ ScalarValue :: $variant( value) => Ok ( * value) ,
44
+ other => Err ( unexpected_literal_value( other) ) ,
45
+ }
46
+ } ;
47
+ }
48
+
40
49
#[ pymethods]
41
50
impl PyLiteral {
42
51
/// Get the data type of this literal value
43
52
fn data_type ( & self ) -> String {
44
53
format ! ( "{}" , self . value. get_datatype( ) )
45
54
}
46
55
47
- fn value_i32 ( & self ) -> PyResult < i32 > {
48
- if let ScalarValue :: Int32 ( Some ( n) ) = & self . value {
49
- Ok ( * n)
50
- } else {
51
- Err ( py_runtime_err ( "Cannot access value as i32" ) )
56
+ pub fn value_f32 ( & self ) -> PyResult < Option < f32 > > {
57
+ extract_scalar_value ! ( self , Float32 )
58
+ }
59
+
60
+ pub fn value_f64 ( & self ) -> PyResult < Option < f64 > > {
61
+ extract_scalar_value ! ( self , Float64 )
62
+ }
63
+
64
+ pub fn value_decimal128 ( & mut self ) -> PyResult < ( Option < i128 > , u8 , i8 ) > {
65
+ match & self . value {
66
+ ScalarValue :: Decimal128 ( value, precision, scale) => Ok ( ( * value, * precision, * scale) ) ,
67
+ other => Err ( unexpected_literal_value ( other) ) ,
68
+ }
69
+ }
70
+
71
+ pub fn value_i8 ( & self ) -> PyResult < Option < i8 > > {
72
+ extract_scalar_value ! ( self , Int8 )
73
+ }
74
+
75
+ pub fn value_i16 ( & self ) -> PyResult < Option < i16 > > {
76
+ extract_scalar_value ! ( self , Int16 )
77
+ }
78
+
79
+ pub fn value_i32 ( & self ) -> PyResult < Option < i32 > > {
80
+ extract_scalar_value ! ( self , Int32 )
81
+ }
82
+
83
+ pub fn value_i64 ( & self ) -> PyResult < Option < i64 > > {
84
+ extract_scalar_value ! ( self , Int64 )
85
+ }
86
+
87
+ pub fn value_u8 ( & self ) -> PyResult < Option < u8 > > {
88
+ extract_scalar_value ! ( self , UInt8 )
89
+ }
90
+
91
+ pub fn value_u16 ( & self ) -> PyResult < Option < u16 > > {
92
+ extract_scalar_value ! ( self , UInt16 )
93
+ }
94
+
95
+ pub fn value_u32 ( & self ) -> PyResult < Option < u32 > > {
96
+ extract_scalar_value ! ( self , UInt32 )
97
+ }
98
+
99
+ pub fn value_u64 ( & self ) -> PyResult < Option < u64 > > {
100
+ extract_scalar_value ! ( self , UInt64 )
101
+ }
102
+
103
+ pub fn value_date32 ( & self ) -> PyResult < Option < i32 > > {
104
+ extract_scalar_value ! ( self , Date32 )
105
+ }
106
+
107
+ pub fn value_date64 ( & self ) -> PyResult < Option < i64 > > {
108
+ extract_scalar_value ! (
9E88
self , Date64 )
109
+ }
110
+
111
+ pub fn value_time64 ( & self ) -> PyResult < Option < i64 > > {
112
+ extract_scalar_value ! ( self , Time64Nanosecond )
113
+ }
114
+
115
+ pub fn value_timestamp ( & mut self ) -> PyResult < ( Option < i64 > , Option < String > ) > {
116
+ match & self . value {
117
+ ScalarValue :: TimestampNanosecond ( iv, tz)
118
+ | ScalarValue :: TimestampMicrosecond ( iv, tz)
119
+ | ScalarValue :: TimestampMillisecond ( iv, tz)
120
+ | ScalarValue :: TimestampSecond ( iv, tz) => Ok ( ( * iv, tz. clone ( ) ) ) ,
121
+ other => Err ( unexpected_literal_value ( other) ) ,
52
122
}
53
123
}
54
124
55
- fn value_i64 ( & self ) -> PyResult < i64 > {
56
- if let ScalarValue :: Int64 ( Some ( n) ) = & self . value {
57
- Ok ( * n)
58
- } else {
59
- Err ( py_runtime_err ( "Cannot access value as i64" ) )
125
+ pub fn value_bool ( & self ) -> PyResult < Option < bool > > {
126
+ extract_scalar_value ! ( self , Boolean )
127
+ }
128
+
129
+ pub fn value_string ( & self ) -> PyResult < Option < String > > {
130
+ match & self . value {
131
+ ScalarValue :: Utf8 ( value) => Ok ( value. clone ( ) ) ,
132
+ other => Err ( unexpected_literal_value ( other) ) ,
60
133
}
61
134
}
62
135
63
- fn value_str ( & self ) -> PyResult < String > {
64
- if let ScalarValue :: Utf8 ( Some ( str) ) = & self . value {
65
- Ok ( str. clone ( ) )
66
- } else {
67
- Err ( py_runtime_err ( "Cannot access value as string" ) )
136
+ pub fn value_interval_day_time ( & self ) -> PyResult < Option < ( i32 , i32 ) > > {
137
+ match & self . value {
138
+ ScalarValue :: IntervalDayTime ( Some ( iv) ) => {
139
+ let interval = * iv as u64 ;
140
+ let days = ( interval >> 32 ) as i32 ;
141
+ let ms = interval as i32 ;
142
+ Ok ( Some ( ( days, ms) ) )
143
+ }
144
+ ScalarValue :: IntervalDayTime ( None ) => Ok ( None ) ,
145
+ other => Err ( unexpected_literal_value ( other) ) ,
68
146
}
69
147
}
70
148
149
+ #[ allow( clippy:: wrong_self_convention) ]
150
+ fn into_type ( & self , py : Python ) -> PyResult < PyObject > {
151
+ Ok ( self . clone ( ) . into_py ( py) )
152
+ }
153
+
71
154
fn __repr__ ( & self ) -> PyResult < String > {
72
155
Ok ( format ! ( "{}" , self . value) )
73
156
}
74
157
}
158
+
159
+ fn unexpected_literal_value ( value : & ScalarValue ) -> PyErr {
160
+ DataFusionError :: Common ( format ! ( "getValue<T>() - Unexpected value: {value}" ) ) . into ( )
161
+ }
0 commit comments