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