mz_expr/scalar/func/impls/
int32.rs1use mz_expr_derive::sqlfunc;
11use mz_ore::cast::ReinterpretCast;
12use mz_repr::adt::numeric::{self, Numeric, NumericMaxScale};
13use mz_repr::adt::system::{Oid, PgLegacyChar};
14use mz_repr::{SqlScalarType, strconv};
15use serde::{Deserialize, Serialize};
16
17use crate::EvalError;
18
19#[sqlfunc(
20 sqlname = "-",
21 preserves_uniqueness = true,
22 inverse = NegInt32,
23 is_monotone = true
24)]
25fn neg_int32(a: i32) -> Result<i32, EvalError> {
26 a.checked_neg()
27 .ok_or_else(|| EvalError::Int32OutOfRange(a.to_string().into()))
28}
29
30#[sqlfunc(
31 sqlname = "~",
32 preserves_uniqueness = true,
33 inverse = BitNotInt32
34)]
35fn bit_not_int32(a: i32) -> i32 {
36 !a
37}
38
39#[sqlfunc(sqlname = "abs")]
40fn abs_int32(a: i32) -> Result<i32, EvalError> {
41 a.checked_abs()
42 .ok_or_else(|| EvalError::Int32OutOfRange(a.to_string().into()))
43}
44
45#[sqlfunc(
46 sqlname = "integer_to_boolean",
47 preserves_uniqueness = false,
48 inverse = super::CastBoolToInt32
49)]
50fn cast_int32_to_bool(a: i32) -> bool {
51 a != 0
52}
53
54#[sqlfunc(
55 sqlname = "integer_to_real",
56 preserves_uniqueness = false,
57 inverse = super::CastFloat32ToInt32,
58 is_monotone = true
59)]
60fn cast_int32_to_float32(a: i32) -> f32 {
61 #[allow(clippy::as_conversions)]
63 {
64 a as f32
65 }
66}
67
68#[sqlfunc(
69 sqlname = "integer_to_double",
70 preserves_uniqueness = true,
71 inverse = super::CastFloat64ToInt32,
72 is_monotone = true
73)]
74fn cast_int32_to_float64(a: i32) -> f64 {
75 f64::from(a)
76}
77
78#[sqlfunc(
79 sqlname = "integer_to_smallint",
80 preserves_uniqueness = true,
81 inverse = super::CastInt16ToInt32,
82 is_monotone = true
83)]
84fn cast_int32_to_int16(a: i32) -> Result<i16, EvalError> {
85 i16::try_from(a).or_else(|_| Err(EvalError::Int16OutOfRange(a.to_string().into())))
86}
87
88#[sqlfunc(
89 sqlname = "integer_to_bigint",
90 preserves_uniqueness = true,
91 inverse = super::CastInt64ToInt32,
92 is_monotone = true
93)]
94fn cast_int32_to_int64(a: i32) -> i64 {
95 i64::from(a)
96}
97
98#[sqlfunc(
99 sqlname = "integer_to_text",
100 preserves_uniqueness = true,
101 inverse = super::CastStringToInt32
102)]
103fn cast_int32_to_string(a: i32) -> String {
104 let mut buf = String::new();
105 strconv::format_int32(&mut buf, a);
106 buf
107}
108
109#[sqlfunc(
110 sqlname = "integer_to_uint2",
111 preserves_uniqueness = true,
112 inverse = super::CastUint16ToInt32,
113 is_monotone = true
114)]
115fn cast_int32_to_uint16(a: i32) -> Result<u16, EvalError> {
116 u16::try_from(a).or_else(|_| Err(EvalError::UInt16OutOfRange(a.to_string().into())))
117}
118
119#[sqlfunc(
120 sqlname = "integer_to_uint4",
121 preserves_uniqueness = true,
122 inverse = super::CastUint32ToInt32,
123 is_monotone = true
124)]
125fn cast_int32_to_uint32(a: i32) -> Result<u32, EvalError> {
126 u32::try_from(a).or_else(|_| Err(EvalError::UInt32OutOfRange(a.to_string().into())))
127}
128
129#[sqlfunc(
130 sqlname = "integer_to_uint8",
131 preserves_uniqueness = true,
132 inverse = super::CastUint64ToInt32,
133 is_monotone = true
134)]
135fn cast_int32_to_uint64(a: i32) -> Result<u64, EvalError> {
136 u64::try_from(a).or_else(|_| Err(EvalError::UInt64OutOfRange(a.to_string().into())))
137}
138
139#[derive(
140 Ord,
141 PartialOrd,
142 Clone,
143 Debug,
144 Eq,
145 PartialEq,
146 Serialize,
147 Deserialize,
148 Hash
149)]
150pub struct CastInt32ToNumeric(pub Option<NumericMaxScale>);
151
152#[sqlfunc(
153 CastInt32ToNumeric,
154 sqlname = "integer_to_numeric",
155 could_error = self.0.is_some(),
156 inverse = super::CastNumericToInt32,
157 is_monotone = true,
158 output_type_expr = SqlScalarType::Numeric { max_scale: self.0 }
159 .nullable(input_type.nullable)
160)]
161fn cast_int32_to_numeric(&self, a: i32) -> Result<Numeric, EvalError> {
162 let mut a = Numeric::from(a);
163 if let Some(scale) = self.0 {
164 if numeric::rescale(&mut a, scale.into_u8()).is_err() {
165 return Err(EvalError::NumericFieldOverflow);
166 }
167 }
168 Ok(a)
170}
171
172#[sqlfunc(
173 sqlname = "integer_to_oid",
174 preserves_uniqueness = true,
175 inverse = super::CastOidToInt32
176)]
177fn cast_int32_to_oid(a: i32) -> Oid {
178 Oid(u32::reinterpret_cast(a))
186}
187
188#[sqlfunc(
189 sqlname = "integer_to_\"char\"",
190 preserves_uniqueness = true,
191 inverse = super::CastPgLegacyCharToInt32
192)]
193fn cast_int32_to_pg_legacy_char(a: i32) -> Result<PgLegacyChar, EvalError> {
194 let a = i8::try_from(a).map_err(|_| EvalError::CharOutOfRange)?;
198 Ok(PgLegacyChar(u8::reinterpret_cast(a)))
199}
200
201#[sqlfunc]
202fn chr(a: i32) -> Result<String, EvalError> {
203 let codepoint = u32::try_from(a).map_err(|_| EvalError::CharacterTooLargeForEncoding(a))?;
206 if codepoint == 0 {
207 Err(EvalError::NullCharacterNotPermitted)
208 } else if 0xd800 <= codepoint && codepoint < 0xe000 {
209 Err(EvalError::CharacterNotValidForEncoding(a))
211 } else {
212 char::from_u32(codepoint)
213 .map(|u| u.to_string())
214 .ok_or(EvalError::CharacterTooLargeForEncoding(a))
215 }
216}