datafusion_functions/math/
ceil.rs1use std::any::Any;
19use std::sync::Arc;
20
21use arrow::array::{ArrayRef, AsArray};
22use arrow::datatypes::{
23 DataType, Decimal32Type, Decimal64Type, Decimal128Type, Decimal256Type, Float32Type,
24 Float64Type,
25};
26use datafusion_common::{Result, ScalarValue, exec_err};
27use datafusion_expr::interval_arithmetic::Interval;
28use datafusion_expr::sort_properties::{ExprProperties, SortProperties};
29use datafusion_expr::{
30 Coercion, ColumnarValue, Documentation, ScalarFunctionArgs, ScalarUDFImpl, Signature,
31 TypeSignature, TypeSignatureClass, Volatility,
32};
33use datafusion_macros::user_doc;
34
35use super::decimal::{apply_decimal_op, ceil_decimal_value};
36
37#[user_doc(
38 doc_section(label = "Math Functions"),
39 description = "Returns the nearest integer greater than or equal to a number.",
40 syntax_example = "ceil(numeric_expression)",
41 standard_argument(name = "numeric_expression", prefix = "Numeric"),
42 sql_example = r#"```sql
43> SELECT ceil(3.14);
44+------------+
45| ceil(3.14) |
46+------------+
47| 4.0 |
48+------------+
49```"#
50)]
51#[derive(Debug, PartialEq, Eq, Hash)]
52pub struct CeilFunc {
53 signature: Signature,
54}
55
56impl Default for CeilFunc {
57 fn default() -> Self {
58 Self::new()
59 }
60}
61
62impl CeilFunc {
63 pub fn new() -> Self {
64 let decimal_sig = Coercion::new_exact(TypeSignatureClass::Decimal);
65 Self {
66 signature: Signature::one_of(
67 vec![
68 TypeSignature::Coercible(vec![decimal_sig]),
69 TypeSignature::Uniform(1, vec![DataType::Float64, DataType::Float32]),
70 ],
71 Volatility::Immutable,
72 ),
73 }
74 }
75}
76
77impl ScalarUDFImpl for CeilFunc {
78 fn as_any(&self) -> &dyn Any {
79 self
80 }
81
82 fn name(&self) -> &str {
83 "ceil"
84 }
85
86 fn signature(&self) -> &Signature {
87 &self.signature
88 }
89
90 fn return_type(&self, arg_types: &[DataType]) -> Result<DataType> {
91 match &arg_types[0] {
92 DataType::Null => Ok(DataType::Float64),
93 other => Ok(other.clone()),
94 }
95 }
96
97 fn invoke_with_args(&self, args: ScalarFunctionArgs) -> Result<ColumnarValue> {
98 let args = ColumnarValue::values_to_arrays(&args.args)?;
99 let value = &args[0];
100
101 let result: ArrayRef = match value.data_type() {
102 DataType::Float64 => Arc::new(
103 value
104 .as_primitive::<Float64Type>()
105 .unary::<_, Float64Type>(f64::ceil),
106 ),
107 DataType::Float32 => Arc::new(
108 value
109 .as_primitive::<Float32Type>()
110 .unary::<_, Float32Type>(f32::ceil),
111 ),
112 DataType::Null => {
113 return Ok(ColumnarValue::Scalar(ScalarValue::Float64(None)));
114 }
115 DataType::Decimal32(precision, scale) => {
116 apply_decimal_op::<Decimal32Type, _>(
117 value,
118 *precision,
119 *scale,
120 self.name(),
121 ceil_decimal_value,
122 )?
123 }
124 DataType::Decimal64(precision, scale) => {
125 apply_decimal_op::<Decimal64Type, _>(
126 value,
127 *precision,
128 *scale,
129 self.name(),
130 ceil_decimal_value,
131 )?
132 }
133 DataType::Decimal128(precision, scale) => {
134 apply_decimal_op::<Decimal128Type, _>(
135 value,
136 *precision,
137 *scale,
138 self.name(),
139 ceil_decimal_value,
140 )?
141 }
142 DataType::Decimal256(precision, scale) => {
143 apply_decimal_op::<Decimal256Type, _>(
144 value,
145 *precision,
146 *scale,
147 self.name(),
148 ceil_decimal_value,
149 )?
150 }
151 other => {
152 return exec_err!(
153 "Unsupported data type {other:?} for function {}",
154 self.name()
155 );
156 }
157 };
158
159 Ok(ColumnarValue::Array(result))
160 }
161
162 fn output_ordering(&self, input: &[ExprProperties]) -> Result<SortProperties> {
163 Ok(input[0].sort_properties)
164 }
165
166 fn evaluate_bounds(&self, inputs: &[&Interval]) -> Result<Interval> {
167 let data_type = inputs[0].data_type();
168 Interval::make_unbounded(&data_type)
169 }
170
171 fn documentation(&self) -> Option<&Documentation> {
172 self.doc()
173 }
174}