mz_expr/scalar/func/impls/
int16.rs

1// Copyright Materialize, Inc. and contributors. All rights reserved.
2//
3// Use of this software is governed by the Business Source License
4// included in the LICENSE file.
5//
6// As of the Change Date specified in that file, in accordance with
7// the Business Source License, use of this software will be governed
8// by the Apache License, Version 2.0.
9
10use std::fmt;
11
12use mz_lowertest::MzReflect;
13use mz_repr::adt::numeric::{self, Numeric, NumericMaxScale};
14use mz_repr::{ColumnType, ScalarType, strconv};
15use serde::{Deserialize, Serialize};
16
17use crate::EvalError;
18use crate::scalar::func::EagerUnaryFunc;
19
20sqlfunc!(
21    #[sqlname = "-"]
22    #[preserves_uniqueness = true]
23    #[inverse = to_unary!(NegInt16)]
24    #[is_monotone = true]
25    fn neg_int16(a: i16) -> Result<i16, EvalError> {
26        a.checked_neg()
27            .ok_or_else(|| EvalError::Int16OutOfRange(a.to_string().into()))
28    }
29);
30
31sqlfunc!(
32    #[sqlname = "~"]
33    #[preserves_uniqueness = true]
34    #[inverse = to_unary!(BitNotInt16)]
35    fn bit_not_int16(a: i16) -> i16 {
36        !a
37    }
38);
39
40sqlfunc!(
41    #[sqlname = "abs"]
42    fn abs_int16(a: i16) -> Result<i16, EvalError> {
43        a.checked_abs()
44            .ok_or_else(|| EvalError::Int16OutOfRange(a.to_string().into()))
45    }
46);
47
48sqlfunc!(
49    #[sqlname = "smallint_to_real"]
50    #[preserves_uniqueness = true]
51    #[inverse = to_unary!(super::CastFloat32ToInt16)]
52    #[is_monotone = true]
53    fn cast_int16_to_float32(a: i16) -> f32 {
54        f32::from(a)
55    }
56);
57
58sqlfunc!(
59    #[sqlname = "smallint_to_double"]
60    #[preserves_uniqueness = true]
61    #[inverse = to_unary!(super::CastFloat64ToInt16)]
62    #[is_monotone = true]
63    fn cast_int16_to_float64(a: i16) -> f64 {
64        f64::from(a)
65    }
66);
67
68sqlfunc!(
69    #[sqlname = "smallint_to_integer"]
70    #[preserves_uniqueness = true]
71    #[inverse = to_unary!(super::CastInt32ToInt16)]
72    #[is_monotone = true]
73    fn cast_int16_to_int32(a: i16) -> i32 {
74        i32::from(a)
75    }
76);
77
78sqlfunc!(
79    #[sqlname = "smallint_to_bigint"]
80    #[preserves_uniqueness = true]
81    #[inverse = to_unary!(super::CastInt64ToInt16)]
82    #[is_monotone = true]
83    fn cast_int16_to_int64(a: i16) -> i64 {
84        i64::from(a)
85    }
86);
87
88sqlfunc!(
89    #[sqlname = "smallint_to_text"]
90    #[preserves_uniqueness = true]
91    #[inverse = to_unary!(super::CastStringToInt16)]
92    fn cast_int16_to_string(a: i16) -> String {
93        let mut buf = String::new();
94        strconv::format_int16(&mut buf, a);
95        buf
96    }
97);
98
99sqlfunc!(
100    #[sqlname = "smallint_to_uint2"]
101    #[preserves_uniqueness = true]
102    #[inverse = to_unary!(super::CastUint16ToInt16)]
103    #[is_monotone = true]
104    fn cast_int16_to_uint16(a: i16) -> Result<u16, EvalError> {
105        u16::try_from(a).or_else(|_| Err(EvalError::UInt16OutOfRange(a.to_string().into())))
106    }
107);
108
109sqlfunc!(
110    #[sqlname = "smallint_to_uint4"]
111    #[preserves_uniqueness = true]
112    #[inverse = to_unary!(super::CastUint32ToInt16)]
113    #[is_monotone = true]
114    fn cast_int16_to_uint32(a: i16) -> Result<u32, EvalError> {
115        u32::try_from(a).or_else(|_| Err(EvalError::UInt32OutOfRange(a.to_string().into())))
116    }
117);
118
119sqlfunc!(
120    #[sqlname = "smallint_to_uint8"]
121    #[preserves_uniqueness = true]
122    #[inverse = to_unary!(super::CastUint64ToInt16)]
123    #[is_monotone = true]
124    fn cast_int16_to_uint64(a: i16) -> Result<u64, EvalError> {
125        u64::try_from(a).or_else(|_| Err(EvalError::UInt64OutOfRange(a.to_string().into())))
126    }
127);
128
129#[derive(Ord, PartialOrd, Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Hash, MzReflect)]
130pub struct CastInt16ToNumeric(pub Option<NumericMaxScale>);
131
132impl<'a> EagerUnaryFunc<'a> for CastInt16ToNumeric {
133    type Input = i16;
134    type Output = Result<Numeric, EvalError>;
135
136    fn call(&self, a: i16) -> Result<Numeric, EvalError> {
137        let mut a = Numeric::from(i32::from(a));
138        if let Some(scale) = self.0 {
139            if numeric::rescale(&mut a, scale.into_u8()).is_err() {
140                return Err(EvalError::NumericFieldOverflow);
141            }
142        }
143        Ok(a)
144    }
145
146    fn output_type(&self, input: ColumnType) -> ColumnType {
147        ScalarType::Numeric { max_scale: self.0 }.nullable(input.nullable)
148    }
149
150    fn could_error(&self) -> bool {
151        self.0.is_some()
152    }
153
154    fn inverse(&self) -> Option<crate::UnaryFunc> {
155        to_unary!(super::CastNumericToInt16)
156    }
157
158    fn is_monotone(&self) -> bool {
159        true
160    }
161}
162
163impl fmt::Display for CastInt16ToNumeric {
164    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
165        f.write_str("smallint_to_numeric")
166    }
167}