mz_expr/scalar/func/impls/
int16.rs1use std::fmt;
11
12use mz_expr_derive::sqlfunc;
13use mz_lowertest::MzReflect;
14use mz_repr::adt::numeric::{self, Numeric, NumericMaxScale};
15use mz_repr::{SqlColumnType, SqlScalarType, strconv};
16use serde::{Deserialize, Serialize};
17
18use crate::EvalError;
19use crate::scalar::func::EagerUnaryFunc;
20
21#[sqlfunc(
22 sqlname = "-",
23 preserves_uniqueness = true,
24 inverse = to_unary!(NegInt16),
25 is_monotone = true
26)]
27fn neg_int16(a: i16) -> Result<i16, EvalError> {
28 a.checked_neg()
29 .ok_or_else(|| EvalError::Int16OutOfRange(a.to_string().into()))
30}
31
32#[sqlfunc(
33 sqlname = "~",
34 preserves_uniqueness = true,
35 inverse = to_unary!(BitNotInt16)
36)]
37fn bit_not_int16(a: i16) -> i16 {
38 !a
39}
40
41#[sqlfunc(sqlname = "abs")]
42fn abs_int16(a: i16) -> Result<i16, EvalError> {
43 a.checked_abs()
44 .ok_or_else(|| EvalError::Int16OutOfRange(a.to_string().into()))
45}
46
47#[sqlfunc(
48 sqlname = "smallint_to_real",
49 preserves_uniqueness = true,
50 inverse = to_unary!(super::CastFloat32ToInt16),
51 is_monotone = true
52)]
53fn cast_int16_to_float32(a: i16) -> f32 {
54 f32::from(a)
55}
56
57#[sqlfunc(
58 sqlname = "smallint_to_double",
59 preserves_uniqueness = true,
60 inverse = to_unary!(super::CastFloat64ToInt16),
61 is_monotone = true
62)]
63fn cast_int16_to_float64(a: i16) -> f64 {
64 f64::from(a)
65}
66
67#[sqlfunc(
68 sqlname = "smallint_to_integer",
69 preserves_uniqueness = true,
70 inverse = to_unary!(super::CastInt32ToInt16),
71 is_monotone = true
72)]
73fn cast_int16_to_int32(a: i16) -> i32 {
74 i32::from(a)
75}
76
77#[sqlfunc(
78 sqlname = "smallint_to_bigint",
79 preserves_uniqueness = true,
80 inverse = to_unary!(super::CastInt64ToInt16),
81 is_monotone = true
82)]
83fn cast_int16_to_int64(a: i16) -> i64 {
84 i64::from(a)
85}
86
87#[sqlfunc(
88 sqlname = "smallint_to_text",
89 preserves_uniqueness = true,
90 inverse = to_unary!(super::CastStringToInt16)
91)]
92fn 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#[sqlfunc(
99 sqlname = "smallint_to_uint2",
100 preserves_uniqueness = true,
101 inverse = to_unary!(super::CastUint16ToInt16),
102 is_monotone = true
103)]
104fn 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#[sqlfunc(
109 sqlname = "smallint_to_uint4",
110 preserves_uniqueness = true,
111 inverse = to_unary!(super::CastUint32ToInt16),
112 is_monotone = true
113)]
114fn 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#[sqlfunc(
119 sqlname = "smallint_to_uint8",
120 preserves_uniqueness = true,
121 inverse = to_unary!(super::CastUint64ToInt16),
122 is_monotone = true
123)]
124fn 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#[derive(Ord, PartialOrd, Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Hash, MzReflect)]
129pub struct CastInt16ToNumeric(pub Option<NumericMaxScale>);
130
131impl<'a> EagerUnaryFunc<'a> for CastInt16ToNumeric {
132 type Input = i16;
133 type Output = Result<Numeric, EvalError>;
134
135 fn call(&self, a: i16) -> Result<Numeric, EvalError> {
136 let mut a = Numeric::from(i32::from(a));
137 if let Some(scale) = self.0 {
138 if numeric::rescale(&mut a, scale.into_u8()).is_err() {
139 return Err(EvalError::NumericFieldOverflow);
140 }
141 }
142 Ok(a)
143 }
144
145 fn output_type(&self, input: SqlColumnType) -> SqlColumnType {
146 SqlScalarType::Numeric { max_scale: self.0 }.nullable(input.nullable)
147 }
148
149 fn could_error(&self) -> bool {
150 self.0.is_some()
151 }
152
153 fn inverse(&self) -> Option<crate::UnaryFunc> {
154 to_unary!(super::CastNumericToInt16)
155 }
156
157 fn is_monotone(&self) -> bool {
158 true
159 }
160}
161
162impl fmt::Display for CastInt16ToNumeric {
163 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
164 f.write_str("smallint_to_numeric")
165 }
166}