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