mz_expr/scalar/func/impls/
int64.rs1use std::fmt;
11
12use mz_expr_derive::sqlfunc;
13use mz_repr::adt::numeric::{self, Numeric, NumericMaxScale};
14use mz_repr::adt::system::Oid;
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!(NegInt64),
25 is_monotone = true
26)]
27fn neg_int64(a: i64) -> Result<i64, EvalError> {
28 a.checked_neg()
29 .ok_or_else(|| EvalError::Int64OutOfRange(a.to_string().into()))
30}
31
32#[sqlfunc(
33 sqlname = "~",
34 preserves_uniqueness = true,
35 inverse = to_unary!(BitNotInt64)
36)]
37fn bit_not_int64(a: i64) -> i64 {
38 !a
39}
40
41#[sqlfunc(sqlname = "abs")]
42fn abs_int64(a: i64) -> Result<i64, EvalError> {
43 a.checked_abs()
44 .ok_or_else(|| EvalError::Int64OutOfRange(a.to_string().into()))
45}
46
47#[sqlfunc(
48 sqlname = "bigint_to_boolean",
49 preserves_uniqueness = false,
50 inverse = to_unary!(super::CastBoolToInt64)
51)]
52fn cast_int64_to_bool(a: i64) -> bool {
53 a != 0
54}
55
56#[sqlfunc(
57 sqlname = "bigint_to_smallint",
58 preserves_uniqueness = true,
59 inverse = to_unary!(super::CastInt16ToInt64),
60 is_monotone = true
61)]
62fn cast_int64_to_int16(a: i64) -> Result<i16, EvalError> {
63 i16::try_from(a).or_else(|_| Err(EvalError::Int16OutOfRange(a.to_string().into())))
64}
65
66#[sqlfunc(
67 sqlname = "bigint_to_integer",
68 preserves_uniqueness = true,
69 inverse = to_unary!(super::CastInt32ToInt64),
70 is_monotone = true
71)]
72fn cast_int64_to_int32(a: i64) -> Result<i32, EvalError> {
73 i32::try_from(a).or_else(|_| Err(EvalError::Int32OutOfRange(a.to_string().into())))
74}
75
76#[sqlfunc(
77 sqlname = "bigint_to_oid",
78 preserves_uniqueness = true,
79 inverse = to_unary!(super::CastOidToInt64)
80)]
81fn cast_int64_to_oid(a: i64) -> Result<Oid, EvalError> {
82 u32::try_from(a)
85 .map(Oid)
86 .or_else(|_| Err(EvalError::OidOutOfRange(a.to_string().into())))
87}
88
89#[sqlfunc(
90 sqlname = "bigint_to_uint2",
91 preserves_uniqueness = true,
92 inverse = to_unary!(super::CastUint16ToInt64),
93 is_monotone = true
94)]
95fn cast_int64_to_uint16(a: i64) -> Result<u16, EvalError> {
96 u16::try_from(a).or_else(|_| Err(EvalError::UInt16OutOfRange(a.to_string().into())))
97}
98
99#[sqlfunc(
100 sqlname = "bigint_to_uint4",
101 preserves_uniqueness = true,
102 inverse = to_unary!(super::CastUint32ToInt64),
103 is_monotone = true
104)]
105fn cast_int64_to_uint32(a: i64) -> Result<u32, EvalError> {
106 u32::try_from(a).or_else(|_| Err(EvalError::UInt32OutOfRange(a.to_string().into())))
107}
108
109#[sqlfunc(
110 sqlname = "bigint_to_uint8",
111 preserves_uniqueness = true,
112 inverse = to_unary!(super::CastUint64ToInt64),
113 is_monotone = true
114)]
115fn cast_int64_to_uint64(a: i64) -> Result<u64, EvalError> {
116 u64::try_from(a).or_else(|_| Err(EvalError::UInt64OutOfRange(a.to_string().into())))
117}
118
119#[derive(
120 Ord,
121 PartialOrd,
122 Clone,
123 Debug,
124 Eq,
125 PartialEq,
126 Serialize,
127 Deserialize,
128 Hash
129)]
130pub struct CastInt64ToNumeric(pub Option<NumericMaxScale>);
131
132impl EagerUnaryFunc for CastInt64ToNumeric {
133 type Input<'a> = i64;
134 type Output<'a> = Result<Numeric, EvalError>;
135
136 fn call<'a>(&self, a: Self::Input<'a>) -> Self::Output<'a> {
137 let mut a = Numeric::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)
145 }
146
147 fn output_sql_type(&self, input: SqlColumnType) -> SqlColumnType {
148 SqlScalarType::Numeric { max_scale: self.0 }.nullable(input.nullable)
149 }
150
151 fn could_error(&self) -> bool {
152 self.0.is_some()
153 }
154
155 fn inverse(&self) -> Option<crate::UnaryFunc> {
156 to_unary!(super::CastNumericToInt64)
157 }
158
159 fn is_monotone(&self) -> bool {
160 true
161 }
162}
163
164impl fmt::Display for CastInt64ToNumeric {
165 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
166 f.write_str("bigint_to_numeric")
167 }
168}
169
170#[sqlfunc(
171 sqlname = "bigint_to_real",
172 preserves_uniqueness = false,
173 inverse = to_unary!(super::CastFloat32ToInt64),
174 is_monotone = true
175)]
176#[allow(clippy::as_conversions)]
178fn cast_int64_to_float32(a: i64) -> f32 {
179 a as f32
180}
181
182#[sqlfunc(
183 sqlname = "bigint_to_double",
184 preserves_uniqueness = false, inverse = to_unary!(super::CastFloat64ToInt64),
186 is_monotone = true
187)]
188#[allow(clippy::as_conversions)]
190fn cast_int64_to_float64(a: i64) -> f64 {
191 a as f64
192}
193
194#[sqlfunc(
195 sqlname = "bigint_to_text",
196 preserves_uniqueness = true,
197 inverse = to_unary!(super::CastStringToInt64)
198)]
199fn cast_int64_to_string(a: i64) -> String {
200 let mut buf = String::new();
201 strconv::format_int64(&mut buf, a);
202 buf
203}