Skip to main content

mz_expr/scalar/func/impls/
uint64.rs

1// Copyright Materialize, Inc. and contributors. All rights reserved.
2//
3// Use of this software is governed by the Business Source License
4// included in the LICENSE file.
5//
6// As of the Change Date specified in that file, in accordance with
7// the Business Source License, use of this software will be governed
8// by the Apache License, Version 2.0.
9
10use mz_expr_derive::sqlfunc;
11use mz_repr::adt::numeric::{self, Numeric, NumericMaxScale};
12use mz_repr::{SqlScalarType, strconv};
13use serde::{Deserialize, Serialize};
14
15use crate::EvalError;
16
17#[sqlfunc(
18    sqlname = "~",
19    preserves_uniqueness = true,
20    inverse = super::BitNotUint64
21)]
22fn bit_not_uint64(a: u64) -> u64 {
23    !a
24}
25
26#[sqlfunc(
27    sqlname = "uint8_to_real",
28    preserves_uniqueness = false,
29    inverse = super::CastFloat32ToUint64,
30    is_monotone = true
31)]
32fn cast_uint64_to_float32(a: u64) -> f32 {
33    // TODO(benesch): remove potentially dangerous usage of `as`.
34    #[allow(clippy::as_conversions)]
35    {
36        a as f32
37    }
38}
39
40#[sqlfunc(
41    sqlname = "uint8_to_double",
42    preserves_uniqueness = false,
43    inverse = super::CastFloat64ToUint64,
44    is_monotone = true
45)]
46fn cast_uint64_to_float64(a: u64) -> f64 {
47    // TODO(benesch): remove potentially dangerous usage of `as`.
48    #[allow(clippy::as_conversions)]
49    {
50        a as f64
51    }
52}
53
54#[sqlfunc(
55    sqlname = "uint8_to_uint2",
56    preserves_uniqueness = true,
57    inverse = super::CastUint16ToUint64,
58    is_monotone = true
59)]
60fn cast_uint64_to_uint16(a: u64) -> Result<u16, EvalError> {
61    u16::try_from(a).or_else(|_| Err(EvalError::UInt16OutOfRange(a.to_string().into())))
62}
63
64#[sqlfunc(
65    sqlname = "uint8_to_uint4",
66    preserves_uniqueness = true,
67    inverse = super::CastUint32ToUint64,
68    is_monotone = true
69)]
70fn cast_uint64_to_uint32(a: u64) -> Result<u32, EvalError> {
71    u32::try_from(a).or_else(|_| Err(EvalError::UInt32OutOfRange(a.to_string().into())))
72}
73
74#[sqlfunc(
75    sqlname = "uint8_to_smallint",
76    preserves_uniqueness = true,
77    inverse = super::CastInt16ToUint64,
78    is_monotone = true
79)]
80fn cast_uint64_to_int16(a: u64) -> Result<i16, EvalError> {
81    i16::try_from(a).or_else(|_| Err(EvalError::Int16OutOfRange(a.to_string().into())))
82}
83
84#[sqlfunc(
85    sqlname = "uint8_to_integer",
86    preserves_uniqueness = true,
87    inverse = super::CastInt32ToUint64,
88    is_monotone = true
89)]
90fn cast_uint64_to_int32(a: u64) -> Result<i32, EvalError> {
91    i32::try_from(a).or_else(|_| Err(EvalError::Int32OutOfRange(a.to_string().into())))
92}
93
94#[sqlfunc(
95    sqlname = "uint8_to_bigint",
96    preserves_uniqueness = true,
97    inverse = super::CastInt64ToUint64,
98    is_monotone = true
99)]
100fn cast_uint64_to_int64(a: u64) -> Result<i64, EvalError> {
101    i64::try_from(a).or_else(|_| Err(EvalError::Int64OutOfRange(a.to_string().into())))
102}
103
104#[sqlfunc(
105    sqlname = "uint8_to_text",
106    preserves_uniqueness = true,
107    inverse = super::CastStringToUint64
108)]
109fn cast_uint64_to_string(a: u64) -> String {
110    let mut buf = String::new();
111    strconv::format_uint64(&mut buf, a);
112    buf
113}
114
115#[derive(
116    Ord,
117    PartialOrd,
118    Clone,
119    Debug,
120    Eq,
121    PartialEq,
122    Serialize,
123    Deserialize,
124    Hash
125)]
126pub struct CastUint64ToNumeric(pub Option<NumericMaxScale>);
127
128#[sqlfunc(
129    CastUint64ToNumeric,
130    sqlname = "uint8_to_numeric",
131    could_error = self.0.is_some(),
132    inverse = super::CastNumericToUint64,
133    is_monotone = true,
134    output_type_expr = SqlScalarType::Numeric { max_scale: self.0 }
135        .nullable(input_type.nullable)
136)]
137fn cast_uint64_to_numeric(&self, a: u64) -> Result<Numeric, EvalError> {
138    let mut a = Numeric::from(a);
139    if let Some(scale) = self.0 {
140        if numeric::rescale(&mut a, scale.into_u8()).is_err() {
141            return Err(EvalError::NumericFieldOverflow);
142        }
143    }
144    // Besides `rescale`, cast is infallible.
145    Ok(a)
146}