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_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}