1
1
//! Module for parsing an `IntermediateDecimal` into a `Decimal75`.
2
- use crate :: {
3
- base:: {
4
- math:: decimal:: DecimalError :: {
5
- IntermediateDecimalConversionError , InvalidPrecision , RoundingError ,
6
- } ,
7
- scalar:: Scalar ,
8
- } ,
9
- sql:: parse:: {
10
- ConversionError :: { self , DecimalConversionError } ,
11
- ConversionResult ,
12
- } ,
13
- } ;
2
+ use crate :: base:: scalar:: { Scalar , ScalarConversionError } ;
14
3
use proof_of_sql_parser:: intermediate_decimal:: { IntermediateDecimal , IntermediateDecimalError } ;
15
4
use serde:: { Deserialize , Deserializer , Serialize } ;
16
5
use thiserror:: Error ;
@@ -42,13 +31,17 @@ pub enum DecimalError {
42
31
43
32
/// Errors that may occur when parsing an intermediate decimal
44
33
/// into a posql decimal
45
- #[ error( "Intermediate decimal conversion error: {0}" ) ]
46
- IntermediateDecimalConversionError ( IntermediateDecimalError ) ,
34
+ #[ error( transparent ) ]
35
+ IntermediateDecimalConversionError ( # [ from ] IntermediateDecimalError ) ,
47
36
}
48
37
49
- impl From < IntermediateDecimalError > for ConversionError {
50
- fn from ( err : IntermediateDecimalError ) -> ConversionError {
51
- DecimalConversionError ( IntermediateDecimalConversionError ( err) )
38
+ /// Result type for decimal operations.
39
+ pub type DecimalResult < T > = Result < T , DecimalError > ;
40
+
41
+ // This exists because `TryFrom<arrow::datatypes::DataType>` for `ColumnType` error is String
42
+ impl From < DecimalError > for String {
43
+ fn from ( error : DecimalError ) -> Self {
44
+ error. to_string ( )
52
45
}
53
46
}
54
47
@@ -59,12 +52,12 @@ pub(crate) const MAX_SUPPORTED_PRECISION: u8 = 75;
59
52
60
53
impl Precision {
61
54
/// Constructor for creating a Precision instance
62
- pub fn new ( value : u8 ) -> Result < Self , ConversionError > {
55
+ pub fn new ( value : u8 ) -> Result < Self , DecimalError > {
63
56
if value > MAX_SUPPORTED_PRECISION || value == 0 {
64
- Err ( DecimalConversionError ( InvalidPrecision ( format ! (
57
+ Err ( DecimalError :: InvalidPrecision ( format ! (
65
58
"Failed to parse precision. Value of {} exceeds max supported precision of {}" ,
66
59
value, MAX_SUPPORTED_PRECISION
67
- ) ) ) )
60
+ ) ) )
68
61
} else {
69
62
Ok ( Precision ( value) )
70
63
}
@@ -116,48 +109,48 @@ impl<S: Scalar> Decimal<S> {
116
109
& self ,
117
110
new_precision : Precision ,
118
111
new_scale : i8 ,
119
- ) -> ConversionResult < Decimal < S > > {
112
+ ) -> DecimalResult < Decimal < S > > {
120
113
let scale_factor = new_scale - self . scale ;
121
114
if scale_factor < 0 || new_precision. value ( ) < self . precision . value ( ) + scale_factor as u8 {
122
- return Err ( DecimalConversionError ( RoundingError (
115
+ return Err ( DecimalError :: RoundingError (
123
116
"Scale factor must be non-negative" . to_string ( ) ,
124
- ) ) ) ;
117
+ ) ) ;
125
118
}
126
119
let scaled_value = scale_scalar ( self . value , scale_factor) ?;
127
120
Ok ( Decimal :: new ( scaled_value, new_precision, new_scale) )
128
121
}
129
122
130
123
/// Get a decimal with given precision and scale from an i64
131
- pub fn from_i64 ( value : i64 , precision : Precision , scale : i8 ) -> ConversionResult < Self > {
124
+ pub fn from_i64 ( value : i64 , precision : Precision , scale : i8 ) -> DecimalResult < Self > {
132
125
const MINIMAL_PRECISION : u8 = 19 ;
133
126
let raw_precision = precision. value ( ) ;
134
127
if raw_precision < MINIMAL_PRECISION {
135
- return Err ( DecimalConversionError ( RoundingError (
128
+ return Err ( DecimalError :: RoundingError (
136
129
"Precision must be at least 19" . to_string ( ) ,
137
- ) ) ) ;
130
+ ) ) ;
138
131
}
139
132
if scale < 0 || raw_precision < MINIMAL_PRECISION + scale as u8 {
140
- return Err ( DecimalConversionError ( RoundingError (
133
+ return Err ( DecimalError :: RoundingError (
141
134
"Can not scale down a decimal" . to_string ( ) ,
142
- ) ) ) ;
135
+ ) ) ;
143
136
}
144
137
let scaled_value = scale_scalar ( S :: from ( & value) , scale) ?;
145
138
Ok ( Decimal :: new ( scaled_value, precision, scale) )
146
139
}
147
140
148
141
/// Get a decimal with given precision and scale from an i128
149
- pub fn from_i128 ( value : i128 , precision : Precision , scale : i8 ) -> ConversionResult < Self > {
142
+ pub fn from_i128 ( value : i128 , precision : Precision , scale : i8 ) -> DecimalResult < Self > {
150
143
const MINIMAL_PRECISION : u8 = 39 ;
151
144
let raw_precision = precision. value ( ) ;
152
145
if raw_precision < MINIMAL_PRECISION {
153
- return Err ( DecimalConversionError ( RoundingError (
146
+ return Err ( DecimalError :: RoundingError (
154
147
"Precision must be at least 19" . to_string ( ) ,
155
- ) ) ) ;
148
+ ) ) ;
156
149
}
157
150
if scale < 0 || raw_precision < MINIMAL_PRECISION + scale as u8 {
158
- return Err ( DecimalConversionError ( RoundingError (
151
+ return Err ( DecimalError :: RoundingError (
159
152
"Can not scale down a decimal" . to_string ( ) ,
160
- ) ) ) ;
153
+ ) ) ;
161
154
}
162
155
let scaled_value = scale_scalar ( S :: from ( & value) , scale) ?;
163
156
Ok ( Decimal :: new ( scaled_value, precision, scale) )
@@ -169,7 +162,7 @@ impl<S: Scalar> Decimal<S> {
169
162
/// the decimal to the specified `target_precision` and `target_scale`,
170
163
/// and validates that the adjusted decimal does not exceed the specified precision.
171
164
/// If the conversion is successful, it returns the `Scalar` representation;
172
- /// otherwise, it returns a `ConversionError ` indicating the type of failure
165
+ /// otherwise, it returns a `DecimalError ` indicating the type of failure
173
166
/// (e.g., exceeding precision limits).
174
167
///
175
168
/// ## Arguments
@@ -178,25 +171,26 @@ impl<S: Scalar> Decimal<S> {
178
171
/// * `target_scale` - The scale (number of decimal places) to use in the scalar.
179
172
///
180
173
/// ## Errors
181
- /// Returns `InvalidPrecision` error if the number of digits in
174
+ /// Returns `DecimalError:: InvalidPrecision` error if the number of digits in
182
175
/// the decimal exceeds the `target_precision` before or after adjusting for
183
176
/// `target_scale`, or if the target precision is zero.
184
177
pub ( crate ) fn try_into_to_scalar < S : Scalar > (
185
178
d : & IntermediateDecimal ,
186
179
target_precision : Precision ,
187
180
target_scale : i8 ,
188
- ) -> Result < S , ConversionError > {
181
+ ) -> DecimalResult < S > {
189
182
d. try_into_bigint_with_precision_and_scale ( target_precision. value ( ) , target_scale) ?
190
183
. try_into ( )
184
+ . map_err ( |e : ScalarConversionError | DecimalError :: InvalidDecimal ( e. to_string ( ) ) )
191
185
}
192
186
193
187
/// Scale scalar by the given scale factor. Negative scaling is not allowed.
194
188
/// Note that we do not check for overflow.
195
- pub ( crate ) fn scale_scalar < S : Scalar > ( s : S , scale : i8 ) -> ConversionResult < S > {
189
+ pub ( crate ) fn scale_scalar < S : Scalar > ( s : S , scale : i8 ) -> DecimalResult < S > {
196
190
if scale < 0 {
197
- return Err ( DecimalConversionError ( RoundingError (
191
+ return Err ( DecimalError :: RoundingError (
198
192
"Scale factor must be non-negative" . to_string ( ) ,
199
- ) ) ) ;
193
+ ) ) ;
200
194
}
201
195
let ten = S :: from ( 10 ) ;
202
196
let mut res = s;
0 commit comments