1 // Licensed to the Apache Software Foundation (ASF) under one
2 // or more contributor license agreements.  See the NOTICE file
3 // distributed with this work for additional information
4 // regarding copyright ownership.  The ASF licenses this file
5 // to you under the Apache License, Version 2.0 (the
6 // "License"); you may not use this file except in compliance
7 // with the License.  You may obtain a copy of the License at
8 //
9 //   http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing,
12 // software distributed under the License is distributed on an
13 // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 // KIND, either express or implied.  See the License for the
15 // specific language governing permissions and limitations
16 // under the License.
17 
18 //! Literal expression
19 
20 use std::any::Any;
21 use std::sync::Arc;
22 
23 use arrow::{
24     datatypes::{DataType, Schema},
25     record_batch::RecordBatch,
26 };
27 
28 use crate::physical_plan::{ColumnarValue, PhysicalExpr};
29 use crate::{error::Result, scalar::ScalarValue};
30 
31 /// Represents a literal value
32 #[derive(Debug)]
33 pub struct Literal {
34     value: ScalarValue,
35 }
36 
37 impl Literal {
38     /// Create a literal value expression
new(value: ScalarValue) -> Self39     pub fn new(value: ScalarValue) -> Self {
40         Self { value }
41     }
42 
43     /// Get the scalar value
value(&self) -> &ScalarValue44     pub fn value(&self) -> &ScalarValue {
45         &self.value
46     }
47 }
48 
49 impl std::fmt::Display for Literal {
fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result50     fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
51         write!(f, "{}", self.value)
52     }
53 }
54 
55 impl PhysicalExpr for Literal {
56     /// Return a reference to Any that can be used for downcasting
as_any(&self) -> &dyn Any57     fn as_any(&self) -> &dyn Any {
58         self
59     }
60 
data_type(&self, _input_schema: &Schema) -> Result<DataType>61     fn data_type(&self, _input_schema: &Schema) -> Result<DataType> {
62         Ok(self.value.get_datatype())
63     }
64 
nullable(&self, _input_schema: &Schema) -> Result<bool>65     fn nullable(&self, _input_schema: &Schema) -> Result<bool> {
66         Ok(self.value.is_null())
67     }
68 
evaluate(&self, _batch: &RecordBatch) -> Result<ColumnarValue>69     fn evaluate(&self, _batch: &RecordBatch) -> Result<ColumnarValue> {
70         Ok(ColumnarValue::Scalar(self.value.clone()))
71     }
72 }
73 
74 /// Create a literal expression
lit(value: ScalarValue) -> Arc<dyn PhysicalExpr>75 pub fn lit(value: ScalarValue) -> Arc<dyn PhysicalExpr> {
76     Arc::new(Literal::new(value))
77 }
78 
79 #[cfg(test)]
80 mod tests {
81     use super::*;
82     use crate::error::Result;
83     use arrow::array::Int32Array;
84     use arrow::datatypes::*;
85 
86     #[test]
literal_i32() -> Result<()>87     fn literal_i32() -> Result<()> {
88         // create an arbitrary record bacth
89         let schema = Schema::new(vec![Field::new("a", DataType::Int32, false)]);
90         let a = Int32Array::from(vec![Some(1), None, Some(3), Some(4), Some(5)]);
91         let batch = RecordBatch::try_new(Arc::new(schema), vec![Arc::new(a)])?;
92 
93         // create and evaluate a literal expression
94         let literal_expr = lit(ScalarValue::from(42i32));
95         assert_eq!("42", format!("{}", literal_expr));
96 
97         let literal_array = literal_expr.evaluate(&batch)?.into_array(batch.num_rows());
98         let literal_array = literal_array.as_any().downcast_ref::<Int32Array>().unwrap();
99 
100         // note that the contents of the literal array are unrelated to the batch contents except for the length of the array
101         assert_eq!(literal_array.len(), 5); // 5 rows in the batch
102         for i in 0..literal_array.len() {
103             assert_eq!(literal_array.value(i), 42);
104         }
105 
106         Ok(())
107     }
108 }
109