Skip to main content

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