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