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(Ord, PartialOrd, Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Hash, MzReflect)]
121pub struct CastInt64ToNumeric(pub Option<NumericMaxScale>);
122
123impl<'a> EagerUnaryFunc<'a> for CastInt64ToNumeric {
124 type Input = i64;
125 type Output = Result<Numeric, EvalError>;
126
127 fn call(&self, a: i64) -> Result<Numeric, EvalError> {
128 let mut a = Numeric::from(a);
129 if let Some(scale) = self.0 {
130 if numeric::rescale(&mut a, scale.into_u8()).is_err() {
131 return Err(EvalError::NumericFieldOverflow);
132 }
133 }
134 Ok(a)
136 }
137
138 fn output_type(&self, input: SqlColumnType) -> SqlColumnType {
139 SqlScalarType::Numeric { max_scale: self.0 }.nullable(input.nullable)
140 }
141
142 fn could_error(&self) -> bool {
143 self.0.is_some()
144 }
145
146 fn inverse(&self) -> Option<crate::UnaryFunc> {
147 to_unary!(super::CastNumericToInt64)
148 }
149
150 fn is_monotone(&self) -> bool {
151 true
152 }
153}
154
155impl fmt::Display for CastInt64ToNumeric {
156 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
157 f.write_str("bigint_to_numeric")
158 }
159}
160
161#[sqlfunc(
162 sqlname = "bigint_to_real",
163 preserves_uniqueness = false,
164 inverse = to_unary!(super::CastFloat32ToInt64),
165 is_monotone = true
166)]
167#[allow(clippy::as_conversions)]
169fn cast_int64_to_float32(a: i64) -> f32 {
170 a as f32
171}
172
173#[sqlfunc(
174 sqlname = "bigint_to_double",
175 preserves_uniqueness = false, inverse = to_unary!(super::CastFloat64ToInt64),
177 is_monotone = true
178)]
179#[allow(clippy::as_conversions)]
181fn cast_int64_to_float64(a: i64) -> f64 {
182 a as f64
183}
184
185#[sqlfunc(
186 sqlname = "bigint_to_text",
187 preserves_uniqueness = true,
188 inverse = to_unary!(super::CastStringToInt64)
189)]
190fn cast_int64_to_string(a: i64) -> String {
191 let mut buf = String::new();
192 strconv::format_int64(&mut buf, a);
193 buf
194}