/Users/andrewlamb/Software/arrow-rs/arrow-array/src/types.rs
Line | Count | Source |
1 | | // Licensed to the Apache Software Foundation (ASF) under one |
2 | | // or more contributor license agreements. See the NOTICE file |
3 | | // distributed with this work for additional information |
4 | | // regarding copyright ownership. The ASF licenses this file |
5 | | // to you under the Apache License, Version 2.0 (the |
6 | | // "License"); you may not use this file except in compliance |
7 | | // with the License. You may obtain a copy of the License at |
8 | | // |
9 | | // http://www.apache.org/licenses/LICENSE-2.0 |
10 | | // |
11 | | // Unless required by applicable law or agreed to in writing, |
12 | | // software distributed under the License is distributed on an |
13 | | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
14 | | // KIND, either express or implied. See the License for the |
15 | | // specific language governing permissions and limitations |
16 | | // under the License. |
17 | | |
18 | | //! Zero-sized types used to parameterize generic array implementations |
19 | | |
20 | | use crate::delta::{ |
21 | | add_days_datetime, add_months_datetime, shift_months, sub_days_datetime, sub_months_datetime, |
22 | | }; |
23 | | use crate::temporal_conversions::as_datetime_with_timezone; |
24 | | use crate::timezone::Tz; |
25 | | use crate::{ArrowNativeTypeOp, OffsetSizeTrait}; |
26 | | use arrow_buffer::{i256, Buffer, OffsetBuffer}; |
27 | | use arrow_data::decimal::{ |
28 | | is_validate_decimal256_precision, is_validate_decimal32_precision, |
29 | | is_validate_decimal64_precision, is_validate_decimal_precision, validate_decimal256_precision, |
30 | | validate_decimal32_precision, validate_decimal64_precision, validate_decimal_precision, |
31 | | }; |
32 | | use arrow_data::{validate_binary_view, validate_string_view}; |
33 | | use arrow_schema::{ |
34 | | ArrowError, DataType, IntervalUnit, TimeUnit, DECIMAL128_MAX_PRECISION, DECIMAL128_MAX_SCALE, |
35 | | DECIMAL256_MAX_PRECISION, DECIMAL256_MAX_SCALE, DECIMAL32_DEFAULT_SCALE, |
36 | | DECIMAL32_MAX_PRECISION, DECIMAL32_MAX_SCALE, DECIMAL64_DEFAULT_SCALE, DECIMAL64_MAX_PRECISION, |
37 | | DECIMAL64_MAX_SCALE, DECIMAL_DEFAULT_SCALE, |
38 | | }; |
39 | | use chrono::{Duration, NaiveDate, NaiveDateTime}; |
40 | | use half::f16; |
41 | | use std::fmt::Debug; |
42 | | use std::marker::PhantomData; |
43 | | use std::ops::{Add, Sub}; |
44 | | |
45 | | // re-export types so that they can be used without importing arrow_buffer explicitly |
46 | | pub use arrow_buffer::{IntervalDayTime, IntervalMonthDayNano}; |
47 | | |
48 | | // BooleanType is special: its bit-width is not the size of the primitive type, and its `index` |
49 | | // operation assumes bit-packing. |
50 | | /// A boolean datatype |
51 | | #[derive(Debug)] |
52 | | pub struct BooleanType {} |
53 | | |
54 | | impl BooleanType { |
55 | | /// The corresponding Arrow data type |
56 | | pub const DATA_TYPE: DataType = DataType::Boolean; |
57 | | } |
58 | | |
59 | | /// Trait for [primitive values]. |
60 | | /// |
61 | | /// This trait bridges the dynamic-typed nature of Arrow |
62 | | /// (via [`DataType`]) with the static-typed nature of rust types |
63 | | /// ([`ArrowNativeType`]) for all types that implement [`ArrowNativeType`]. |
64 | | /// |
65 | | /// [primitive values]: https://arrow.apache.org/docs/format/Columnar.html#fixed-size-primitive-layout |
66 | | /// [`ArrowNativeType`]: arrow_buffer::ArrowNativeType |
67 | | pub trait ArrowPrimitiveType: primitive::PrimitiveTypeSealed + 'static { |
68 | | /// Corresponding Rust native type for the primitive type. |
69 | | type Native: ArrowNativeTypeOp; |
70 | | |
71 | | /// the corresponding Arrow data type of this primitive type. |
72 | | const DATA_TYPE: DataType; |
73 | | |
74 | | /// Returns a default value of this primitive type. |
75 | | /// |
76 | | /// This is useful for aggregate array ops like `sum()`, `mean()`. |
77 | 0 | fn default_value() -> Self::Native { |
78 | 0 | Default::default() |
79 | 0 | } |
80 | | } |
81 | | |
82 | | mod primitive { |
83 | | pub trait PrimitiveTypeSealed {} |
84 | | } |
85 | | |
86 | | macro_rules! make_type { |
87 | | ($name:ident, $native_ty:ty, $data_ty:expr, $doc_string: literal) => { |
88 | | #[derive(Debug)] |
89 | | #[doc = $doc_string] |
90 | | pub struct $name {} |
91 | | |
92 | | impl ArrowPrimitiveType for $name { |
93 | | type Native = $native_ty; |
94 | | const DATA_TYPE: DataType = $data_ty; |
95 | | } |
96 | | |
97 | | impl primitive::PrimitiveTypeSealed for $name {} |
98 | | }; |
99 | | } |
100 | | |
101 | | make_type!(Int8Type, i8, DataType::Int8, "A signed 8-bit integer type."); |
102 | | make_type!( |
103 | | Int16Type, |
104 | | i16, |
105 | | DataType::Int16, |
106 | | "Signed 16-bit integer type." |
107 | | ); |
108 | | make_type!( |
109 | | Int32Type, |
110 | | i32, |
111 | | DataType::Int32, |
112 | | "Signed 32-bit integer type." |
113 | | ); |
114 | | make_type!( |
115 | | Int64Type, |
116 | | i64, |
117 | | DataType::Int64, |
118 | | "Signed 64-bit integer type." |
119 | | ); |
120 | | make_type!( |
121 | | UInt8Type, |
122 | | u8, |
123 | | DataType::UInt8, |
124 | | "Unsigned 8-bit integer type." |
125 | | ); |
126 | | make_type!( |
127 | | UInt16Type, |
128 | | u16, |
129 | | DataType::UInt16, |
130 | | "Unsigned 16-bit integer type." |
131 | | ); |
132 | | make_type!( |
133 | | UInt32Type, |
134 | | u32, |
135 | | DataType::UInt32, |
136 | | "Unsigned 32-bit integer type." |
137 | | ); |
138 | | make_type!( |
139 | | UInt64Type, |
140 | | u64, |
141 | | DataType::UInt64, |
142 | | "Unsigned 64-bit integer type." |
143 | | ); |
144 | | make_type!( |
145 | | Float16Type, |
146 | | f16, |
147 | | DataType::Float16, |
148 | | "16-bit floating point number type." |
149 | | ); |
150 | | make_type!( |
151 | | Float32Type, |
152 | | f32, |
153 | | DataType::Float32, |
154 | | "32-bit floating point number type." |
155 | | ); |
156 | | make_type!( |
157 | | Float64Type, |
158 | | f64, |
159 | | DataType::Float64, |
160 | | "64-bit floating point number type." |
161 | | ); |
162 | | make_type!( |
163 | | TimestampSecondType, |
164 | | i64, |
165 | | DataType::Timestamp(TimeUnit::Second, None), |
166 | | "Timestamp second type with an optional timezone." |
167 | | ); |
168 | | make_type!( |
169 | | TimestampMillisecondType, |
170 | | i64, |
171 | | DataType::Timestamp(TimeUnit::Millisecond, None), |
172 | | "Timestamp millisecond type with an optional timezone." |
173 | | ); |
174 | | make_type!( |
175 | | TimestampMicrosecondType, |
176 | | i64, |
177 | | DataType::Timestamp(TimeUnit::Microsecond, None), |
178 | | "Timestamp microsecond type with an optional timezone." |
179 | | ); |
180 | | make_type!( |
181 | | TimestampNanosecondType, |
182 | | i64, |
183 | | DataType::Timestamp(TimeUnit::Nanosecond, None), |
184 | | "Timestamp nanosecond type with an optional timezone." |
185 | | ); |
186 | | make_type!( |
187 | | Date32Type, |
188 | | i32, |
189 | | DataType::Date32, |
190 | | "32-bit date type: the elapsed time since UNIX epoch in days (32 bits)." |
191 | | ); |
192 | | make_type!( |
193 | | Date64Type, |
194 | | i64, |
195 | | DataType::Date64, |
196 | | "64-bit date type: the elapsed time since UNIX epoch in milliseconds (64 bits). \ |
197 | | Values must be divisible by `86_400_000`. \ |
198 | | See [`DataType::Date64`] for more details." |
199 | | ); |
200 | | make_type!( |
201 | | Time32SecondType, |
202 | | i32, |
203 | | DataType::Time32(TimeUnit::Second), |
204 | | "32-bit time type: the elapsed time since midnight in seconds." |
205 | | ); |
206 | | make_type!( |
207 | | Time32MillisecondType, |
208 | | i32, |
209 | | DataType::Time32(TimeUnit::Millisecond), |
210 | | "32-bit time type: the elapsed time since midnight in milliseconds." |
211 | | ); |
212 | | make_type!( |
213 | | Time64MicrosecondType, |
214 | | i64, |
215 | | DataType::Time64(TimeUnit::Microsecond), |
216 | | "64-bit time type: the elapsed time since midnight in microseconds." |
217 | | ); |
218 | | make_type!( |
219 | | Time64NanosecondType, |
220 | | i64, |
221 | | DataType::Time64(TimeUnit::Nanosecond), |
222 | | "64-bit time type: the elapsed time since midnight in nanoseconds." |
223 | | ); |
224 | | make_type!( |
225 | | IntervalYearMonthType, |
226 | | i32, |
227 | | DataType::Interval(IntervalUnit::YearMonth), |
228 | | "32-bit “calendar” interval type: the number of whole months." |
229 | | ); |
230 | | make_type!( |
231 | | IntervalDayTimeType, |
232 | | IntervalDayTime, |
233 | | DataType::Interval(IntervalUnit::DayTime), |
234 | | "“Calendar” interval type: days and milliseconds. See [`IntervalDayTime`] for more details." |
235 | | ); |
236 | | make_type!( |
237 | | IntervalMonthDayNanoType, |
238 | | IntervalMonthDayNano, |
239 | | DataType::Interval(IntervalUnit::MonthDayNano), |
240 | | r"“Calendar” interval type: months, days, and nanoseconds. See [`IntervalMonthDayNano`] for more details." |
241 | | ); |
242 | | make_type!( |
243 | | DurationSecondType, |
244 | | i64, |
245 | | DataType::Duration(TimeUnit::Second), |
246 | | "Elapsed time type: seconds." |
247 | | ); |
248 | | make_type!( |
249 | | DurationMillisecondType, |
250 | | i64, |
251 | | DataType::Duration(TimeUnit::Millisecond), |
252 | | "Elapsed time type: milliseconds." |
253 | | ); |
254 | | make_type!( |
255 | | DurationMicrosecondType, |
256 | | i64, |
257 | | DataType::Duration(TimeUnit::Microsecond), |
258 | | "Elapsed time type: microseconds." |
259 | | ); |
260 | | make_type!( |
261 | | DurationNanosecondType, |
262 | | i64, |
263 | | DataType::Duration(TimeUnit::Nanosecond), |
264 | | "Elapsed time type: nanoseconds." |
265 | | ); |
266 | | |
267 | | /// A subtype of primitive type that represents legal dictionary keys. |
268 | | /// See <https://arrow.apache.org/docs/format/Columnar.html> |
269 | | pub trait ArrowDictionaryKeyType: ArrowPrimitiveType {} |
270 | | |
271 | | impl ArrowDictionaryKeyType for Int8Type {} |
272 | | |
273 | | impl ArrowDictionaryKeyType for Int16Type {} |
274 | | |
275 | | impl ArrowDictionaryKeyType for Int32Type {} |
276 | | |
277 | | impl ArrowDictionaryKeyType for Int64Type {} |
278 | | |
279 | | impl ArrowDictionaryKeyType for UInt8Type {} |
280 | | |
281 | | impl ArrowDictionaryKeyType for UInt16Type {} |
282 | | |
283 | | impl ArrowDictionaryKeyType for UInt32Type {} |
284 | | |
285 | | impl ArrowDictionaryKeyType for UInt64Type {} |
286 | | |
287 | | /// A subtype of primitive type that is used as run-ends index |
288 | | /// in `RunArray`. |
289 | | /// See <https://arrow.apache.org/docs/format/Columnar.html> |
290 | | pub trait RunEndIndexType: ArrowPrimitiveType {} |
291 | | |
292 | | impl RunEndIndexType for Int16Type {} |
293 | | |
294 | | impl RunEndIndexType for Int32Type {} |
295 | | |
296 | | impl RunEndIndexType for Int64Type {} |
297 | | |
298 | | /// A subtype of primitive type that represents temporal values. |
299 | | pub trait ArrowTemporalType: ArrowPrimitiveType {} |
300 | | |
301 | | impl ArrowTemporalType for TimestampSecondType {} |
302 | | impl ArrowTemporalType for TimestampMillisecondType {} |
303 | | impl ArrowTemporalType for TimestampMicrosecondType {} |
304 | | impl ArrowTemporalType for TimestampNanosecondType {} |
305 | | impl ArrowTemporalType for Date32Type {} |
306 | | impl ArrowTemporalType for Date64Type {} |
307 | | impl ArrowTemporalType for Time32SecondType {} |
308 | | impl ArrowTemporalType for Time32MillisecondType {} |
309 | | impl ArrowTemporalType for Time64MicrosecondType {} |
310 | | impl ArrowTemporalType for Time64NanosecondType {} |
311 | | // impl ArrowTemporalType for IntervalYearMonthType {} |
312 | | // impl ArrowTemporalType for IntervalDayTimeType {} |
313 | | // impl ArrowTemporalType for IntervalMonthDayNanoType {} |
314 | | impl ArrowTemporalType for DurationSecondType {} |
315 | | impl ArrowTemporalType for DurationMillisecondType {} |
316 | | impl ArrowTemporalType for DurationMicrosecondType {} |
317 | | impl ArrowTemporalType for DurationNanosecondType {} |
318 | | |
319 | | /// A timestamp type allows us to create array builders that take a timestamp. |
320 | | pub trait ArrowTimestampType: ArrowTemporalType<Native = i64> { |
321 | | /// The [`TimeUnit`] of this timestamp. |
322 | | const UNIT: TimeUnit; |
323 | | |
324 | | /// Creates a ArrowTimestampType::Native from the provided [`NaiveDateTime`] |
325 | | /// |
326 | | /// See [`DataType::Timestamp`] for more information on timezone handling |
327 | | fn make_value(naive: NaiveDateTime) -> Option<i64>; |
328 | | } |
329 | | |
330 | | impl ArrowTimestampType for TimestampSecondType { |
331 | | const UNIT: TimeUnit = TimeUnit::Second; |
332 | | |
333 | 0 | fn make_value(naive: NaiveDateTime) -> Option<i64> { |
334 | 0 | Some(naive.and_utc().timestamp()) |
335 | 0 | } |
336 | | } |
337 | | impl ArrowTimestampType for TimestampMillisecondType { |
338 | | const UNIT: TimeUnit = TimeUnit::Millisecond; |
339 | | |
340 | 0 | fn make_value(naive: NaiveDateTime) -> Option<i64> { |
341 | 0 | let utc = naive.and_utc(); |
342 | 0 | let millis = utc.timestamp().checked_mul(1_000)?; |
343 | 0 | millis.checked_add(utc.timestamp_subsec_millis() as i64) |
344 | 0 | } |
345 | | } |
346 | | impl ArrowTimestampType for TimestampMicrosecondType { |
347 | | const UNIT: TimeUnit = TimeUnit::Microsecond; |
348 | | |
349 | 0 | fn make_value(naive: NaiveDateTime) -> Option<i64> { |
350 | 0 | let utc = naive.and_utc(); |
351 | 0 | let micros = utc.timestamp().checked_mul(1_000_000)?; |
352 | 0 | micros.checked_add(utc.timestamp_subsec_micros() as i64) |
353 | 0 | } |
354 | | } |
355 | | impl ArrowTimestampType for TimestampNanosecondType { |
356 | | const UNIT: TimeUnit = TimeUnit::Nanosecond; |
357 | | |
358 | 0 | fn make_value(naive: NaiveDateTime) -> Option<i64> { |
359 | 0 | let utc = naive.and_utc(); |
360 | 0 | let nanos = utc.timestamp().checked_mul(1_000_000_000)?; |
361 | 0 | nanos.checked_add(utc.timestamp_subsec_nanos() as i64) |
362 | 0 | } |
363 | | } |
364 | | |
365 | 0 | fn add_year_months<T: ArrowTimestampType>( |
366 | 0 | timestamp: <T as ArrowPrimitiveType>::Native, |
367 | 0 | delta: <IntervalYearMonthType as ArrowPrimitiveType>::Native, |
368 | 0 | tz: Tz, |
369 | 0 | ) -> Option<<T as ArrowPrimitiveType>::Native> { |
370 | 0 | let months = IntervalYearMonthType::to_months(delta); |
371 | 0 | let res = as_datetime_with_timezone::<T>(timestamp, tz)?; |
372 | 0 | let res = add_months_datetime(res, months)?; |
373 | 0 | let res = res.naive_utc(); |
374 | 0 | T::make_value(res) |
375 | 0 | } |
376 | | |
377 | 0 | fn add_day_time<T: ArrowTimestampType>( |
378 | 0 | timestamp: <T as ArrowPrimitiveType>::Native, |
379 | 0 | delta: <IntervalDayTimeType as ArrowPrimitiveType>::Native, |
380 | 0 | tz: Tz, |
381 | 0 | ) -> Option<<T as ArrowPrimitiveType>::Native> { |
382 | 0 | let (days, ms) = IntervalDayTimeType::to_parts(delta); |
383 | 0 | let res = as_datetime_with_timezone::<T>(timestamp, tz)?; |
384 | 0 | let res = add_days_datetime(res, days)?; |
385 | 0 | let res = res.checked_add_signed(Duration::try_milliseconds(ms as i64)?)?; |
386 | 0 | let res = res.naive_utc(); |
387 | 0 | T::make_value(res) |
388 | 0 | } |
389 | | |
390 | 0 | fn add_month_day_nano<T: ArrowTimestampType>( |
391 | 0 | timestamp: <T as ArrowPrimitiveType>::Native, |
392 | 0 | delta: <IntervalMonthDayNanoType as ArrowPrimitiveType>::Native, |
393 | 0 | tz: Tz, |
394 | 0 | ) -> Option<<T as ArrowPrimitiveType>::Native> { |
395 | 0 | let (months, days, nanos) = IntervalMonthDayNanoType::to_parts(delta); |
396 | 0 | let res = as_datetime_with_timezone::<T>(timestamp, tz)?; |
397 | 0 | let res = add_months_datetime(res, months)?; |
398 | 0 | let res = add_days_datetime(res, days)?; |
399 | 0 | let res = res.checked_add_signed(Duration::nanoseconds(nanos))?; |
400 | 0 | let res = res.naive_utc(); |
401 | 0 | T::make_value(res) |
402 | 0 | } |
403 | | |
404 | 0 | fn subtract_year_months<T: ArrowTimestampType>( |
405 | 0 | timestamp: <T as ArrowPrimitiveType>::Native, |
406 | 0 | delta: <IntervalYearMonthType as ArrowPrimitiveType>::Native, |
407 | 0 | tz: Tz, |
408 | 0 | ) -> Option<<T as ArrowPrimitiveType>::Native> { |
409 | 0 | let months = IntervalYearMonthType::to_months(delta); |
410 | 0 | let res = as_datetime_with_timezone::<T>(timestamp, tz)?; |
411 | 0 | let res = sub_months_datetime(res, months)?; |
412 | 0 | let res = res.naive_utc(); |
413 | 0 | T::make_value(res) |
414 | 0 | } |
415 | | |
416 | 0 | fn subtract_day_time<T: ArrowTimestampType>( |
417 | 0 | timestamp: <T as ArrowPrimitiveType>::Native, |
418 | 0 | delta: <IntervalDayTimeType as ArrowPrimitiveType>::Native, |
419 | 0 | tz: Tz, |
420 | 0 | ) -> Option<<T as ArrowPrimitiveType>::Native> { |
421 | 0 | let (days, ms) = IntervalDayTimeType::to_parts(delta); |
422 | 0 | let res = as_datetime_with_timezone::<T>(timestamp, tz)?; |
423 | 0 | let res = sub_days_datetime(res, days)?; |
424 | 0 | let res = res.checked_sub_signed(Duration::try_milliseconds(ms as i64)?)?; |
425 | 0 | let res = res.naive_utc(); |
426 | 0 | T::make_value(res) |
427 | 0 | } |
428 | | |
429 | 0 | fn subtract_month_day_nano<T: ArrowTimestampType>( |
430 | 0 | timestamp: <T as ArrowPrimitiveType>::Native, |
431 | 0 | delta: <IntervalMonthDayNanoType as ArrowPrimitiveType>::Native, |
432 | 0 | tz: Tz, |
433 | 0 | ) -> Option<<T as ArrowPrimitiveType>::Native> { |
434 | 0 | let (months, days, nanos) = IntervalMonthDayNanoType::to_parts(delta); |
435 | 0 | let res = as_datetime_with_timezone::<T>(timestamp, tz)?; |
436 | 0 | let res = sub_months_datetime(res, months)?; |
437 | 0 | let res = sub_days_datetime(res, days)?; |
438 | 0 | let res = res.checked_sub_signed(Duration::nanoseconds(nanos))?; |
439 | 0 | let res = res.naive_utc(); |
440 | 0 | T::make_value(res) |
441 | 0 | } |
442 | | |
443 | | impl TimestampSecondType { |
444 | | /// Adds the given IntervalYearMonthType to an arrow TimestampSecondType. |
445 | | /// |
446 | | /// Returns `None` when it will result in overflow. |
447 | | /// |
448 | | /// # Arguments |
449 | | /// |
450 | | /// * `timestamp` - The date on which to perform the operation |
451 | | /// * `delta` - The interval to add |
452 | | /// * `tz` - The timezone in which to interpret `timestamp` |
453 | 0 | pub fn add_year_months( |
454 | 0 | timestamp: <Self as ArrowPrimitiveType>::Native, |
455 | 0 | delta: <IntervalYearMonthType as ArrowPrimitiveType>::Native, |
456 | 0 | tz: Tz, |
457 | 0 | ) -> Option<<Self as ArrowPrimitiveType>::Native> { |
458 | 0 | add_year_months::<Self>(timestamp, delta, tz) |
459 | 0 | } |
460 | | |
461 | | /// Adds the given IntervalDayTimeType to an arrow TimestampSecondType. |
462 | | /// |
463 | | /// Returns `None` when it will result in overflow. |
464 | | /// |
465 | | /// # Arguments |
466 | | /// |
467 | | /// * `timestamp` - The date on which to perform the operation |
468 | | /// * `delta` - The interval to add |
469 | | /// * `tz` - The timezone in which to interpret `timestamp` |
470 | 0 | pub fn add_day_time( |
471 | 0 | timestamp: <Self as ArrowPrimitiveType>::Native, |
472 | 0 | delta: <IntervalDayTimeType as ArrowPrimitiveType>::Native, |
473 | 0 | tz: Tz, |
474 | 0 | ) -> Option<<Self as ArrowPrimitiveType>::Native> { |
475 | 0 | add_day_time::<Self>(timestamp, delta, tz) |
476 | 0 | } |
477 | | |
478 | | /// Adds the given IntervalMonthDayNanoType to an arrow TimestampSecondType |
479 | | /// |
480 | | /// Returns `None` when it will result in overflow. |
481 | | /// # Arguments |
482 | | /// |
483 | | /// * `timestamp` - The date on which to perform the operation |
484 | | /// * `delta` - The interval to add |
485 | | /// * `tz` - The timezone in which to interpret `timestamp` |
486 | 0 | pub fn add_month_day_nano( |
487 | 0 | timestamp: <Self as ArrowPrimitiveType>::Native, |
488 | 0 | delta: <IntervalMonthDayNanoType as ArrowPrimitiveType>::Native, |
489 | 0 | tz: Tz, |
490 | 0 | ) -> Option<<Self as ArrowPrimitiveType>::Native> { |
491 | 0 | add_month_day_nano::<Self>(timestamp, delta, tz) |
492 | 0 | } |
493 | | |
494 | | /// Subtracts the given IntervalYearMonthType to an arrow TimestampSecondType |
495 | | /// |
496 | | /// Returns `None` when it will result in overflow. |
497 | | /// |
498 | | /// # Arguments |
499 | | /// |
500 | | /// * `timestamp` - The date on which to perform the operation |
501 | | /// * `delta` - The interval to add |
502 | | /// * `tz` - The timezone in which to interpret `timestamp` |
503 | 0 | pub fn subtract_year_months( |
504 | 0 | timestamp: <Self as ArrowPrimitiveType>::Native, |
505 | 0 | delta: <IntervalYearMonthType as ArrowPrimitiveType>::Native, |
506 | 0 | tz: Tz, |
507 | 0 | ) -> Option<<Self as ArrowPrimitiveType>::Native> { |
508 | 0 | subtract_year_months::<Self>(timestamp, delta, tz) |
509 | 0 | } |
510 | | |
511 | | /// Subtracts the given IntervalDayTimeType to an arrow TimestampSecondType |
512 | | /// |
513 | | /// Returns `None` when it will result in overflow. |
514 | | /// |
515 | | /// # Arguments |
516 | | /// |
517 | | /// * `timestamp` - The date on which to perform the operation |
518 | | /// * `delta` - The interval to add |
519 | | /// * `tz` - The timezone in which to interpret `timestamp` |
520 | 0 | pub fn subtract_day_time( |
521 | 0 | timestamp: <Self as ArrowPrimitiveType>::Native, |
522 | 0 | delta: <IntervalDayTimeType as ArrowPrimitiveType>::Native, |
523 | 0 | tz: Tz, |
524 | 0 | ) -> Option<<Self as ArrowPrimitiveType>::Native> { |
525 | 0 | subtract_day_time::<Self>(timestamp, delta, tz) |
526 | 0 | } |
527 | | |
528 | | /// Subtracts the given IntervalMonthDayNanoType to an arrow TimestampSecondType |
529 | | /// |
530 | | /// Returns `None` when it will result in overflow. |
531 | | /// |
532 | | /// # Arguments |
533 | | /// |
534 | | /// * `timestamp` - The date on which to perform the operation |
535 | | /// * `delta` - The interval to add |
536 | | /// * `tz` - The timezone in which to interpret `timestamp` |
537 | 0 | pub fn subtract_month_day_nano( |
538 | 0 | timestamp: <Self as ArrowPrimitiveType>::Native, |
539 | 0 | delta: <IntervalMonthDayNanoType as ArrowPrimitiveType>::Native, |
540 | 0 | tz: Tz, |
541 | 0 | ) -> Option<<Self as ArrowPrimitiveType>::Native> { |
542 | 0 | subtract_month_day_nano::<Self>(timestamp, delta, tz) |
543 | 0 | } |
544 | | } |
545 | | |
546 | | impl TimestampMicrosecondType { |
547 | | /// Adds the given IntervalYearMonthType to an arrow TimestampMicrosecondType |
548 | | /// |
549 | | /// # Arguments |
550 | | /// |
551 | | /// * `timestamp` - The date on which to perform the operation |
552 | | /// * `delta` - The interval to add |
553 | | /// * `tz` - The timezone in which to interpret `timestamp` |
554 | 0 | pub fn add_year_months( |
555 | 0 | timestamp: <Self as ArrowPrimitiveType>::Native, |
556 | 0 | delta: <IntervalYearMonthType as ArrowPrimitiveType>::Native, |
557 | 0 | tz: Tz, |
558 | 0 | ) -> Option<<Self as ArrowPrimitiveType>::Native> { |
559 | 0 | add_year_months::<Self>(timestamp, delta, tz) |
560 | 0 | } |
561 | | |
562 | | /// Adds the given IntervalDayTimeType to an arrow TimestampMicrosecondType |
563 | | /// |
564 | | /// # Arguments |
565 | | /// |
566 | | /// * `timestamp` - The date on which to perform the operation |
567 | | /// * `delta` - The interval to add |
568 | | /// * `tz` - The timezone in which to interpret `timestamp` |
569 | 0 | pub fn add_day_time( |
570 | 0 | timestamp: <Self as ArrowPrimitiveType>::Native, |
571 | 0 | delta: <IntervalDayTimeType as ArrowPrimitiveType>::Native, |
572 | 0 | tz: Tz, |
573 | 0 | ) -> Option<<Self as ArrowPrimitiveType>::Native> { |
574 | 0 | add_day_time::<Self>(timestamp, delta, tz) |
575 | 0 | } |
576 | | |
577 | | /// Adds the given IntervalMonthDayNanoType to an arrow TimestampMicrosecondType |
578 | | /// |
579 | | /// # Arguments |
580 | | /// |
581 | | /// * `timestamp` - The date on which to perform the operation |
582 | | /// * `delta` - The interval to add |
583 | | /// * `tz` - The timezone in which to interpret `timestamp` |
584 | 0 | pub fn add_month_day_nano( |
585 | 0 | timestamp: <Self as ArrowPrimitiveType>::Native, |
586 | 0 | delta: <IntervalMonthDayNanoType as ArrowPrimitiveType>::Native, |
587 | 0 | tz: Tz, |
588 | 0 | ) -> Option<<Self as ArrowPrimitiveType>::Native> { |
589 | 0 | add_month_day_nano::<Self>(timestamp, delta, tz) |
590 | 0 | } |
591 | | |
592 | | /// Subtracts the given IntervalYearMonthType to an arrow TimestampMicrosecondType |
593 | | /// |
594 | | /// # Arguments |
595 | | /// |
596 | | /// * `timestamp` - The date on which to perform the operation |
597 | | /// * `delta` - The interval to add |
598 | | /// * `tz` - The timezone in which to interpret `timestamp` |
599 | 0 | pub fn subtract_year_months( |
600 | 0 | timestamp: <Self as ArrowPrimitiveType>::Native, |
601 | 0 | delta: <IntervalYearMonthType as ArrowPrimitiveType>::Native, |
602 | 0 | tz: Tz, |
603 | 0 | ) -> Option<<Self as ArrowPrimitiveType>::Native> { |
604 | 0 | subtract_year_months::<Self>(timestamp, delta, tz) |
605 | 0 | } |
606 | | |
607 | | /// Subtracts the given IntervalDayTimeType to an arrow TimestampMicrosecondType |
608 | | /// |
609 | | /// # Arguments |
610 | | /// |
611 | | /// * `timestamp` - The date on which to perform the operation |
612 | | /// * `delta` - The interval to add |
613 | | /// * `tz` - The timezone in which to interpret `timestamp` |
614 | 0 | pub fn subtract_day_time( |
615 | 0 | timestamp: <Self as ArrowPrimitiveType>::Native, |
616 | 0 | delta: <IntervalDayTimeType as ArrowPrimitiveType>::Native, |
617 | 0 | tz: Tz, |
618 | 0 | ) -> Option<<Self as ArrowPrimitiveType>::Native> { |
619 | 0 | subtract_day_time::<Self>(timestamp, delta, tz) |
620 | 0 | } |
621 | | |
622 | | /// Subtracts the given IntervalMonthDayNanoType to an arrow TimestampMicrosecondType |
623 | | /// |
624 | | /// # Arguments |
625 | | /// |
626 | | /// * `timestamp` - The date on which to perform the operation |
627 | | /// * `delta` - The interval to add |
628 | | /// * `tz` - The timezone in which to interpret `timestamp` |
629 | 0 | pub fn subtract_month_day_nano( |
630 | 0 | timestamp: <Self as ArrowPrimitiveType>::Native, |
631 | 0 | delta: <IntervalMonthDayNanoType as ArrowPrimitiveType>::Native, |
632 | 0 | tz: Tz, |
633 | 0 | ) -> Option<<Self as ArrowPrimitiveType>::Native> { |
634 | 0 | subtract_month_day_nano::<Self>(timestamp, delta, tz) |
635 | 0 | } |
636 | | } |
637 | | |
638 | | impl TimestampMillisecondType { |
639 | | /// Adds the given IntervalYearMonthType to an arrow TimestampMillisecondType |
640 | | /// |
641 | | /// # Arguments |
642 | | /// |
643 | | /// * `timestamp` - The date on which to perform the operation |
644 | | /// * `delta` - The interval to add |
645 | | /// * `tz` - The timezone in which to interpret `timestamp` |
646 | 0 | pub fn add_year_months( |
647 | 0 | timestamp: <Self as ArrowPrimitiveType>::Native, |
648 | 0 | delta: <IntervalYearMonthType as ArrowPrimitiveType>::Native, |
649 | 0 | tz: Tz, |
650 | 0 | ) -> Option<<Self as ArrowPrimitiveType>::Native> { |
651 | 0 | add_year_months::<Self>(timestamp, delta, tz) |
652 | 0 | } |
653 | | |
654 | | /// Adds the given IntervalDayTimeType to an arrow TimestampMillisecondType |
655 | | /// |
656 | | /// # Arguments |
657 | | /// |
658 | | /// * `timestamp` - The date on which to perform the operation |
659 | | /// * `delta` - The interval to add |
660 | | /// * `tz` - The timezone in which to interpret `timestamp` |
661 | 0 | pub fn add_day_time( |
662 | 0 | timestamp: <Self as ArrowPrimitiveType>::Native, |
663 | 0 | delta: <IntervalDayTimeType as ArrowPrimitiveType>::Native, |
664 | 0 | tz: Tz, |
665 | 0 | ) -> Option<<Self as ArrowPrimitiveType>::Native> { |
666 | 0 | add_day_time::<Self>(timestamp, delta, tz) |
667 | 0 | } |
668 | | |
669 | | /// Adds the given IntervalMonthDayNanoType to an arrow TimestampMillisecondType |
670 | | /// |
671 | | /// # Arguments |
672 | | /// |
673 | | /// * `timestamp` - The date on which to perform the operation |
674 | | /// * `delta` - The interval to add |
675 | | /// * `tz` - The timezone in which to interpret `timestamp` |
676 | 0 | pub fn add_month_day_nano( |
677 | 0 | timestamp: <Self as ArrowPrimitiveType>::Native, |
678 | 0 | delta: <IntervalMonthDayNanoType as ArrowPrimitiveType>::Native, |
679 | 0 | tz: Tz, |
680 | 0 | ) -> Option<<Self as ArrowPrimitiveType>::Native> { |
681 | 0 | add_month_day_nano::<Self>(timestamp, delta, tz) |
682 | 0 | } |
683 | | |
684 | | /// Subtracts the given IntervalYearMonthType to an arrow TimestampMillisecondType |
685 | | /// |
686 | | /// # Arguments |
687 | | /// |
688 | | /// * `timestamp` - The date on which to perform the operation |
689 | | /// * `delta` - The interval to add |
690 | | /// * `tz` - The timezone in which to interpret `timestamp` |
691 | 0 | pub fn subtract_year_months( |
692 | 0 | timestamp: <Self as ArrowPrimitiveType>::Native, |
693 | 0 | delta: <IntervalYearMonthType as ArrowPrimitiveType>::Native, |
694 | 0 | tz: Tz, |
695 | 0 | ) -> Option<<Self as ArrowPrimitiveType>::Native> { |
696 | 0 | subtract_year_months::<Self>(timestamp, delta, tz) |
697 | 0 | } |
698 | | |
699 | | /// Subtracts the given IntervalDayTimeType to an arrow TimestampMillisecondType |
700 | | /// |
701 | | /// # Arguments |
702 | | /// |
703 | | /// * `timestamp` - The date on which to perform the operation |
704 | | /// * `delta` - The interval to add |
705 | | /// * `tz` - The timezone in which to interpret `timestamp` |
706 | 0 | pub fn subtract_day_time( |
707 | 0 | timestamp: <Self as ArrowPrimitiveType>::Native, |
708 | 0 | delta: <IntervalDayTimeType as ArrowPrimitiveType>::Native, |
709 | 0 | tz: Tz, |
710 | 0 | ) -> Option<<Self as ArrowPrimitiveType>::Native> { |
711 | 0 | subtract_day_time::<Self>(timestamp, delta, tz) |
712 | 0 | } |
713 | | |
714 | | /// Subtracts the given IntervalMonthDayNanoType to an arrow TimestampMillisecondType |
715 | | /// |
716 | | /// # Arguments |
717 | | /// |
718 | | /// * `timestamp` - The date on which to perform the operation |
719 | | /// * `delta` - The interval to add |
720 | | /// * `tz` - The timezone in which to interpret `timestamp` |
721 | 0 | pub fn subtract_month_day_nano( |
722 | 0 | timestamp: <Self as ArrowPrimitiveType>::Native, |
723 | 0 | delta: <IntervalMonthDayNanoType as ArrowPrimitiveType>::Native, |
724 | 0 | tz: Tz, |
725 | 0 | ) -> Option<<Self as ArrowPrimitiveType>::Native> { |
726 | 0 | subtract_month_day_nano::<Self>(timestamp, delta, tz) |
727 | 0 | } |
728 | | } |
729 | | |
730 | | impl TimestampNanosecondType { |
731 | | /// Adds the given IntervalYearMonthType to an arrow TimestampNanosecondType |
732 | | /// |
733 | | /// # Arguments |
734 | | /// |
735 | | /// * `timestamp` - The date on which to perform the operation |
736 | | /// * `delta` - The interval to add |
737 | | /// * `tz` - The timezone in which to interpret `timestamp` |
738 | 0 | pub fn add_year_months( |
739 | 0 | timestamp: <Self as ArrowPrimitiveType>::Native, |
740 | 0 | delta: <IntervalYearMonthType as ArrowPrimitiveType>::Native, |
741 | 0 | tz: Tz, |
742 | 0 | ) -> Option<<Self as ArrowPrimitiveType>::Native> { |
743 | 0 | add_year_months::<Self>(timestamp, delta, tz) |
744 | 0 | } |
745 | | |
746 | | /// Adds the given IntervalDayTimeType to an arrow TimestampNanosecondType |
747 | | /// |
748 | | /// # Arguments |
749 | | /// |
750 | | /// * `timestamp` - The date on which to perform the operation |
751 | | /// * `delta` - The interval to add |
752 | | /// * `tz` - The timezone in which to interpret `timestamp` |
753 | 0 | pub fn add_day_time( |
754 | 0 | timestamp: <Self as ArrowPrimitiveType>::Native, |
755 | 0 | delta: <IntervalDayTimeType as ArrowPrimitiveType>::Native, |
756 | 0 | tz: Tz, |
757 | 0 | ) -> Option<<Self as ArrowPrimitiveType>::Native> { |
758 | 0 | add_day_time::<Self>(timestamp, delta, tz) |
759 | 0 | } |
760 | | |
761 | | /// Adds the given IntervalMonthDayNanoType to an arrow TimestampNanosecondType |
762 | | /// |
763 | | /// # Arguments |
764 | | /// |
765 | | /// * `timestamp` - The date on which to perform the operation |
766 | | /// * `delta` - The interval to add |
767 | | /// * `tz` - The timezone in which to interpret `timestamp` |
768 | 0 | pub fn add_month_day_nano( |
769 | 0 | timestamp: <Self as ArrowPrimitiveType>::Native, |
770 | 0 | delta: <IntervalMonthDayNanoType as ArrowPrimitiveType>::Native, |
771 | 0 | tz: Tz, |
772 | 0 | ) -> Option<<Self as ArrowPrimitiveType>::Native> { |
773 | 0 | add_month_day_nano::<Self>(timestamp, delta, tz) |
774 | 0 | } |
775 | | |
776 | | /// Subtracts the given IntervalYearMonthType to an arrow TimestampNanosecondType |
777 | | /// |
778 | | /// # Arguments |
779 | | /// |
780 | | /// * `timestamp` - The date on which to perform the operation |
781 | | /// * `delta` - The interval to add |
782 | | /// * `tz` - The timezone in which to interpret `timestamp` |
783 | 0 | pub fn subtract_year_months( |
784 | 0 | timestamp: <Self as ArrowPrimitiveType>::Native, |
785 | 0 | delta: <IntervalYearMonthType as ArrowPrimitiveType>::Native, |
786 | 0 | tz: Tz, |
787 | 0 | ) -> Option<<Self as ArrowPrimitiveType>::Native> { |
788 | 0 | subtract_year_months::<Self>(timestamp, delta, tz) |
789 | 0 | } |
790 | | |
791 | | /// Subtracts the given IntervalDayTimeType to an arrow TimestampNanosecondType |
792 | | /// |
793 | | /// # Arguments |
794 | | /// |
795 | | /// * `timestamp` - The date on which to perform the operation |
796 | | /// * `delta` - The interval to add |
797 | | /// * `tz` - The timezone in which to interpret `timestamp` |
798 | 0 | pub fn subtract_day_time( |
799 | 0 | timestamp: <Self as ArrowPrimitiveType>::Native, |
800 | 0 | delta: <IntervalDayTimeType as ArrowPrimitiveType>::Native, |
801 | 0 | tz: Tz, |
802 | 0 | ) -> Option<<Self as ArrowPrimitiveType>::Native> { |
803 | 0 | subtract_day_time::<Self>(timestamp, delta, tz) |
804 | 0 | } |
805 | | |
806 | | /// Subtracts the given IntervalMonthDayNanoType to an arrow TimestampNanosecondType |
807 | | /// |
808 | | /// # Arguments |
809 | | /// |
810 | | /// * `timestamp` - The date on which to perform the operation |
811 | | /// * `delta` - The interval to add |
812 | | /// * `tz` - The timezone in which to interpret `timestamp` |
813 | 0 | pub fn subtract_month_day_nano( |
814 | 0 | timestamp: <Self as ArrowPrimitiveType>::Native, |
815 | 0 | delta: <IntervalMonthDayNanoType as ArrowPrimitiveType>::Native, |
816 | 0 | tz: Tz, |
817 | 0 | ) -> Option<<Self as ArrowPrimitiveType>::Native> { |
818 | 0 | subtract_month_day_nano::<Self>(timestamp, delta, tz) |
819 | 0 | } |
820 | | } |
821 | | |
822 | | impl IntervalYearMonthType { |
823 | | /// Creates a IntervalYearMonthType::Native |
824 | | /// |
825 | | /// # Arguments |
826 | | /// |
827 | | /// * `years` - The number of years (+/-) represented in this interval |
828 | | /// * `months` - The number of months (+/-) represented in this interval |
829 | | #[inline] |
830 | 0 | pub fn make_value( |
831 | 0 | years: i32, |
832 | 0 | months: i32, |
833 | 0 | ) -> <IntervalYearMonthType as ArrowPrimitiveType>::Native { |
834 | 0 | years * 12 + months |
835 | 0 | } |
836 | | |
837 | | /// Turns a IntervalYearMonthType type into an i32 of months. |
838 | | /// |
839 | | /// This operation is technically a no-op, it is included for comprehensiveness. |
840 | | /// |
841 | | /// # Arguments |
842 | | /// |
843 | | /// * `i` - The IntervalYearMonthType::Native to convert |
844 | | #[inline] |
845 | 0 | pub fn to_months(i: <IntervalYearMonthType as ArrowPrimitiveType>::Native) -> i32 { |
846 | 0 | i |
847 | 0 | } |
848 | | } |
849 | | |
850 | | impl IntervalDayTimeType { |
851 | | /// Creates a IntervalDayTimeType::Native |
852 | | /// |
853 | | /// # Arguments |
854 | | /// |
855 | | /// * `days` - The number of days (+/-) represented in this interval |
856 | | /// * `millis` - The number of milliseconds (+/-) represented in this interval |
857 | | #[inline] |
858 | 0 | pub fn make_value(days: i32, milliseconds: i32) -> IntervalDayTime { |
859 | 0 | IntervalDayTime { days, milliseconds } |
860 | 0 | } |
861 | | |
862 | | /// Turns a IntervalDayTimeType into a tuple of (days, milliseconds) |
863 | | /// |
864 | | /// # Arguments |
865 | | /// |
866 | | /// * `i` - The IntervalDayTimeType to convert |
867 | | #[inline] |
868 | 0 | pub fn to_parts(i: IntervalDayTime) -> (i32, i32) { |
869 | 0 | (i.days, i.milliseconds) |
870 | 0 | } |
871 | | } |
872 | | |
873 | | impl IntervalMonthDayNanoType { |
874 | | /// Creates a IntervalMonthDayNanoType::Native |
875 | | /// |
876 | | /// # Arguments |
877 | | /// |
878 | | /// * `months` - The number of months (+/-) represented in this interval |
879 | | /// * `days` - The number of days (+/-) represented in this interval |
880 | | /// * `nanos` - The number of nanoseconds (+/-) represented in this interval |
881 | | #[inline] |
882 | 4 | pub fn make_value(months: i32, days: i32, nanoseconds: i64) -> IntervalMonthDayNano { |
883 | 4 | IntervalMonthDayNano { |
884 | 4 | months, |
885 | 4 | days, |
886 | 4 | nanoseconds, |
887 | 4 | } |
888 | 4 | } |
889 | | |
890 | | /// Turns a IntervalMonthDayNanoType into a tuple of (months, days, nanos) |
891 | | /// |
892 | | /// # Arguments |
893 | | /// |
894 | | /// * `i` - The IntervalMonthDayNanoType to convert |
895 | | #[inline] |
896 | 0 | pub fn to_parts(i: IntervalMonthDayNano) -> (i32, i32, i64) { |
897 | 0 | (i.months, i.days, i.nanoseconds) |
898 | 0 | } |
899 | | } |
900 | | |
901 | | impl Date32Type { |
902 | | /// Converts an arrow Date32Type into a chrono::NaiveDate |
903 | | /// |
904 | | /// # Arguments |
905 | | /// |
906 | | /// * `i` - The Date32Type to convert |
907 | 0 | pub fn to_naive_date(i: <Date32Type as ArrowPrimitiveType>::Native) -> NaiveDate { |
908 | 0 | let epoch = NaiveDate::from_ymd_opt(1970, 1, 1).unwrap(); |
909 | 0 | epoch.add(Duration::try_days(i as i64).unwrap()) |
910 | 0 | } |
911 | | |
912 | | /// Converts a chrono::NaiveDate into an arrow Date32Type |
913 | | /// |
914 | | /// # Arguments |
915 | | /// |
916 | | /// * `d` - The NaiveDate to convert |
917 | 0 | pub fn from_naive_date(d: NaiveDate) -> <Date32Type as ArrowPrimitiveType>::Native { |
918 | 0 | let epoch = NaiveDate::from_ymd_opt(1970, 1, 1).unwrap(); |
919 | 0 | d.sub(epoch).num_days() as <Date32Type as ArrowPrimitiveType>::Native |
920 | 0 | } |
921 | | |
922 | | /// Adds the given IntervalYearMonthType to an arrow Date32Type |
923 | | /// |
924 | | /// # Arguments |
925 | | /// |
926 | | /// * `date` - The date on which to perform the operation |
927 | | /// * `delta` - The interval to add |
928 | 0 | pub fn add_year_months( |
929 | 0 | date: <Date32Type as ArrowPrimitiveType>::Native, |
930 | 0 | delta: <IntervalYearMonthType as ArrowPrimitiveType>::Native, |
931 | 0 | ) -> <Date32Type as ArrowPrimitiveType>::Native { |
932 | 0 | let prior = Date32Type::to_naive_date(date); |
933 | 0 | let months = IntervalYearMonthType::to_months(delta); |
934 | 0 | let posterior = shift_months(prior, months); |
935 | 0 | Date32Type::from_naive_date(posterior) |
936 | 0 | } |
937 | | |
938 | | /// Adds the given IntervalDayTimeType to an arrow Date32Type |
939 | | /// |
940 | | /// # Arguments |
941 | | /// |
942 | | /// * `date` - The date on which to perform the operation |
943 | | /// * `delta` - The interval to add |
944 | 0 | pub fn add_day_time( |
945 | 0 | date: <Date32Type as ArrowPrimitiveType>::Native, |
946 | 0 | delta: <IntervalDayTimeType as ArrowPrimitiveType>::Native, |
947 | 0 | ) -> <Date32Type as ArrowPrimitiveType>::Native { |
948 | 0 | let (days, ms) = IntervalDayTimeType::to_parts(delta); |
949 | 0 | let res = Date32Type::to_naive_date(date); |
950 | 0 | let res = res.add(Duration::try_days(days as i64).unwrap()); |
951 | 0 | let res = res.add(Duration::try_milliseconds(ms as i64).unwrap()); |
952 | 0 | Date32Type::from_naive_date(res) |
953 | 0 | } |
954 | | |
955 | | /// Adds the given IntervalMonthDayNanoType to an arrow Date32Type |
956 | | /// |
957 | | /// # Arguments |
958 | | /// |
959 | | /// * `date` - The date on which to perform the operation |
960 | | /// * `delta` - The interval to add |
961 | 0 | pub fn add_month_day_nano( |
962 | 0 | date: <Date32Type as ArrowPrimitiveType>::Native, |
963 | 0 | delta: <IntervalMonthDayNanoType as ArrowPrimitiveType>::Native, |
964 | 0 | ) -> <Date32Type as ArrowPrimitiveType>::Native { |
965 | 0 | let (months, days, nanos) = IntervalMonthDayNanoType::to_parts(delta); |
966 | 0 | let res = Date32Type::to_naive_date(date); |
967 | 0 | let res = shift_months(res, months); |
968 | 0 | let res = res.add(Duration::try_days(days as i64).unwrap()); |
969 | 0 | let res = res.add(Duration::nanoseconds(nanos)); |
970 | 0 | Date32Type::from_naive_date(res) |
971 | 0 | } |
972 | | |
973 | | /// Subtract the given IntervalYearMonthType to an arrow Date32Type |
974 | | /// |
975 | | /// # Arguments |
976 | | /// |
977 | | /// * `date` - The date on which to perform the operation |
978 | | /// * `delta` - The interval to subtract |
979 | 0 | pub fn subtract_year_months( |
980 | 0 | date: <Date32Type as ArrowPrimitiveType>::Native, |
981 | 0 | delta: <IntervalYearMonthType as ArrowPrimitiveType>::Native, |
982 | 0 | ) -> <Date32Type as ArrowPrimitiveType>::Native { |
983 | 0 | let prior = Date32Type::to_naive_date(date); |
984 | 0 | let months = IntervalYearMonthType::to_months(-delta); |
985 | 0 | let posterior = shift_months(prior, months); |
986 | 0 | Date32Type::from_naive_date(posterior) |
987 | 0 | } |
988 | | |
989 | | /// Subtract the given IntervalDayTimeType to an arrow Date32Type |
990 | | /// |
991 | | /// # Arguments |
992 | | /// |
993 | | /// * `date` - The date on which to perform the operation |
994 | | /// * `delta` - The interval to subtract |
995 | 0 | pub fn subtract_day_time( |
996 | 0 | date: <Date32Type as ArrowPrimitiveType>::Native, |
997 | 0 | delta: <IntervalDayTimeType as ArrowPrimitiveType>::Native, |
998 | 0 | ) -> <Date32Type as ArrowPrimitiveType>::Native { |
999 | 0 | let (days, ms) = IntervalDayTimeType::to_parts(delta); |
1000 | 0 | let res = Date32Type::to_naive_date(date); |
1001 | 0 | let res = res.sub(Duration::try_days(days as i64).unwrap()); |
1002 | 0 | let res = res.sub(Duration::try_milliseconds(ms as i64).unwrap()); |
1003 | 0 | Date32Type::from_naive_date(res) |
1004 | 0 | } |
1005 | | |
1006 | | /// Subtract the given IntervalMonthDayNanoType to an arrow Date32Type |
1007 | | /// |
1008 | | /// # Arguments |
1009 | | /// |
1010 | | /// * `date` - The date on which to perform the operation |
1011 | | /// * `delta` - The interval to subtract |
1012 | 0 | pub fn subtract_month_day_nano( |
1013 | 0 | date: <Date32Type as ArrowPrimitiveType>::Native, |
1014 | 0 | delta: <IntervalMonthDayNanoType as ArrowPrimitiveType>::Native, |
1015 | 0 | ) -> <Date32Type as ArrowPrimitiveType>::Native { |
1016 | 0 | let (months, days, nanos) = IntervalMonthDayNanoType::to_parts(delta); |
1017 | 0 | let res = Date32Type::to_naive_date(date); |
1018 | 0 | let res = shift_months(res, -months); |
1019 | 0 | let res = res.sub(Duration::try_days(days as i64).unwrap()); |
1020 | 0 | let res = res.sub(Duration::nanoseconds(nanos)); |
1021 | 0 | Date32Type::from_naive_date(res) |
1022 | 0 | } |
1023 | | } |
1024 | | |
1025 | | impl Date64Type { |
1026 | | /// Converts an arrow Date64Type into a chrono::NaiveDate |
1027 | | /// |
1028 | | /// # Arguments |
1029 | | /// |
1030 | | /// * `i` - The Date64Type to convert |
1031 | | #[deprecated(since = "56.0.0", note = "Use to_naive_date_opt instead.")] |
1032 | 0 | pub fn to_naive_date(i: <Date64Type as ArrowPrimitiveType>::Native) -> NaiveDate { |
1033 | 0 | Self::to_naive_date_opt(i) |
1034 | 0 | .unwrap_or_else(|| panic!("Date64Type::to_naive_date overflowed for date: {i}",)) |
1035 | 0 | } |
1036 | | |
1037 | | /// Converts an arrow Date64Type into a chrono::NaiveDateTime if it fits in the range that chrono::NaiveDateTime can represent. |
1038 | | /// Returns `None` if the calculation would overflow or underflow. |
1039 | | /// |
1040 | | /// This function is able to handle dates ranging between 1677-09-21 (-9,223,372,800,000) and 2262-04-11 (9,223,286,400,000). |
1041 | | /// |
1042 | | /// # Arguments |
1043 | | /// |
1044 | | /// * `i` - The Date64Type to convert |
1045 | | /// |
1046 | | /// Returns `Some(NaiveDateTime)` if it fits, `None` otherwise. |
1047 | 0 | pub fn to_naive_date_opt(i: <Date64Type as ArrowPrimitiveType>::Native) -> Option<NaiveDate> { |
1048 | 0 | let epoch = NaiveDate::from_ymd_opt(1970, 1, 1).unwrap(); |
1049 | 0 | Duration::try_milliseconds(i).and_then(|d| epoch.checked_add_signed(d)) |
1050 | 0 | } |
1051 | | |
1052 | | /// Converts a chrono::NaiveDate into an arrow Date64Type |
1053 | | /// |
1054 | | /// # Arguments |
1055 | | /// |
1056 | | /// * `d` - The NaiveDate to convert |
1057 | 0 | pub fn from_naive_date(d: NaiveDate) -> <Date64Type as ArrowPrimitiveType>::Native { |
1058 | 0 | let epoch = NaiveDate::from_ymd_opt(1970, 1, 1).unwrap(); |
1059 | 0 | d.sub(epoch).num_milliseconds() as <Date64Type as ArrowPrimitiveType>::Native |
1060 | 0 | } |
1061 | | |
1062 | | /// Adds the given IntervalYearMonthType to an arrow Date64Type |
1063 | | /// |
1064 | | /// # Arguments |
1065 | | /// |
1066 | | /// * `date` - The date on which to perform the operation |
1067 | | /// * `delta` - The interval to add |
1068 | | #[deprecated( |
1069 | | since = "56.0.0", |
1070 | | note = "Use `add_year_months_opt` instead, which returns an Option to handle overflow." |
1071 | | )] |
1072 | 0 | pub fn add_year_months( |
1073 | 0 | date: <Date64Type as ArrowPrimitiveType>::Native, |
1074 | 0 | delta: <IntervalYearMonthType as ArrowPrimitiveType>::Native, |
1075 | 0 | ) -> <Date64Type as ArrowPrimitiveType>::Native { |
1076 | 0 | Self::add_year_months_opt(date, delta).unwrap_or_else(|| { |
1077 | 0 | panic!("Date64Type::add_year_months overflowed for date: {date}, delta: {delta}",) |
1078 | | }) |
1079 | 0 | } |
1080 | | |
1081 | | /// Adds the given IntervalYearMonthType to an arrow Date64Type |
1082 | | /// |
1083 | | /// # Arguments |
1084 | | /// |
1085 | | /// * `date` - The date on which to perform the operation |
1086 | | /// * `delta` - The interval to add |
1087 | | /// |
1088 | | /// Returns `Some(Date64Type)` if it fits, `None` otherwise. |
1089 | 0 | pub fn add_year_months_opt( |
1090 | 0 | date: <Date64Type as ArrowPrimitiveType>::Native, |
1091 | 0 | delta: <IntervalYearMonthType as ArrowPrimitiveType>::Native, |
1092 | 0 | ) -> Option<<Date64Type as ArrowPrimitiveType>::Native> { |
1093 | 0 | let prior = Date64Type::to_naive_date_opt(date)?; |
1094 | 0 | let months = IntervalYearMonthType::to_months(delta); |
1095 | 0 | let posterior = shift_months(prior, months); |
1096 | 0 | Some(Date64Type::from_naive_date(posterior)) |
1097 | 0 | } |
1098 | | |
1099 | | /// Adds the given IntervalDayTimeType to an arrow Date64Type |
1100 | | /// |
1101 | | /// # Arguments |
1102 | | /// |
1103 | | /// * `date` - The date on which to perform the operation |
1104 | | /// * `delta` - The interval to add |
1105 | | #[deprecated( |
1106 | | since = "56.0.0", |
1107 | | note = "Use `add_day_time_opt` instead, which returns an Option to handle overflow." |
1108 | | )] |
1109 | 0 | pub fn add_day_time( |
1110 | 0 | date: <Date64Type as ArrowPrimitiveType>::Native, |
1111 | 0 | delta: <IntervalDayTimeType as ArrowPrimitiveType>::Native, |
1112 | 0 | ) -> <Date64Type as ArrowPrimitiveType>::Native { |
1113 | 0 | Self::add_day_time_opt(date, delta).unwrap_or_else(|| { |
1114 | 0 | panic!("Date64Type::add_day_time overflowed for date: {date}, delta: {delta:?}",) |
1115 | | }) |
1116 | 0 | } |
1117 | | |
1118 | | /// Adds the given IntervalDayTimeType to an arrow Date64Type |
1119 | | /// |
1120 | | /// # Arguments |
1121 | | /// |
1122 | | /// * `date` - The date on which to perform the operation |
1123 | | /// * `delta` - The interval to add |
1124 | | /// |
1125 | | /// Returns `Some(Date64Type)` if it fits, `None` otherwise. |
1126 | 0 | pub fn add_day_time_opt( |
1127 | 0 | date: <Date64Type as ArrowPrimitiveType>::Native, |
1128 | 0 | delta: <IntervalDayTimeType as ArrowPrimitiveType>::Native, |
1129 | 0 | ) -> Option<<Date64Type as ArrowPrimitiveType>::Native> { |
1130 | 0 | let (days, ms) = IntervalDayTimeType::to_parts(delta); |
1131 | 0 | let res = Date64Type::to_naive_date_opt(date)?; |
1132 | 0 | let res = res.checked_add_signed(Duration::try_days(days as i64)?)?; |
1133 | 0 | let res = res.checked_add_signed(Duration::try_milliseconds(ms as i64)?)?; |
1134 | 0 | Some(Date64Type::from_naive_date(res)) |
1135 | 0 | } |
1136 | | |
1137 | | /// Adds the given IntervalMonthDayNanoType to an arrow Date64Type |
1138 | | /// |
1139 | | /// # Arguments |
1140 | | /// |
1141 | | /// * `date` - The date on which to perform the operation |
1142 | | /// * `delta` - The interval to add |
1143 | | #[deprecated( |
1144 | | since = "56.0.0", |
1145 | | note = "Use `add_month_day_nano_opt` instead, which returns an Option to handle overflow." |
1146 | | )] |
1147 | 0 | pub fn add_month_day_nano( |
1148 | 0 | date: <Date64Type as ArrowPrimitiveType>::Native, |
1149 | 0 | delta: <IntervalMonthDayNanoType as ArrowPrimitiveType>::Native, |
1150 | 0 | ) -> <Date64Type as ArrowPrimitiveType>::Native { |
1151 | 0 | Self::add_month_day_nano_opt(date, delta).unwrap_or_else(|| { |
1152 | 0 | panic!("Date64Type::add_month_day_nano overflowed for date: {date}, delta: {delta:?}",) |
1153 | | }) |
1154 | 0 | } |
1155 | | |
1156 | | /// Adds the given IntervalMonthDayNanoType to an arrow Date64Type |
1157 | | /// |
1158 | | /// # Arguments |
1159 | | /// |
1160 | | /// * `date` - The date on which to perform the operation |
1161 | | /// * `delta` - The interval to add |
1162 | | /// |
1163 | | /// Returns `Some(Date64Type)` if it fits, `None` otherwise. |
1164 | 0 | pub fn add_month_day_nano_opt( |
1165 | 0 | date: <Date64Type as ArrowPrimitiveType>::Native, |
1166 | 0 | delta: <IntervalMonthDayNanoType as ArrowPrimitiveType>::Native, |
1167 | 0 | ) -> Option<<Date64Type as ArrowPrimitiveType>::Native> { |
1168 | 0 | let (months, days, nanos) = IntervalMonthDayNanoType::to_parts(delta); |
1169 | 0 | let res = Date64Type::to_naive_date_opt(date)?; |
1170 | 0 | let res = shift_months(res, months); |
1171 | 0 | let res = res.checked_add_signed(Duration::try_days(days as i64)?)?; |
1172 | 0 | let res = res.checked_add_signed(Duration::nanoseconds(nanos))?; |
1173 | 0 | Some(Date64Type::from_naive_date(res)) |
1174 | 0 | } |
1175 | | |
1176 | | /// Subtract the given IntervalYearMonthType to an arrow Date64Type |
1177 | | /// |
1178 | | /// # Arguments |
1179 | | /// |
1180 | | /// * `date` - The date on which to perform the operation |
1181 | | /// * `delta` - The interval to subtract |
1182 | | #[deprecated( |
1183 | | since = "56.0.0", |
1184 | | note = "Use `subtract_year_months_opt` instead, which returns an Option to handle overflow." |
1185 | | )] |
1186 | 0 | pub fn subtract_year_months( |
1187 | 0 | date: <Date64Type as ArrowPrimitiveType>::Native, |
1188 | 0 | delta: <IntervalYearMonthType as ArrowPrimitiveType>::Native, |
1189 | 0 | ) -> <Date64Type as ArrowPrimitiveType>::Native { |
1190 | 0 | Self::subtract_year_months_opt(date, delta).unwrap_or_else(|| { |
1191 | 0 | panic!("Date64Type::subtract_year_months overflowed for date: {date}, delta: {delta}",) |
1192 | | }) |
1193 | 0 | } |
1194 | | |
1195 | | /// Subtract the given IntervalYearMonthType to an arrow Date64Type |
1196 | | /// |
1197 | | /// # Arguments |
1198 | | /// |
1199 | | /// * `date` - The date on which to perform the operation |
1200 | | /// * `delta` - The interval to subtract |
1201 | | /// |
1202 | | /// Returns `Some(Date64Type)` if it fits, `None` otherwise. |
1203 | 0 | pub fn subtract_year_months_opt( |
1204 | 0 | date: <Date64Type as ArrowPrimitiveType>::Native, |
1205 | 0 | delta: <IntervalYearMonthType as ArrowPrimitiveType>::Native, |
1206 | 0 | ) -> Option<<Date64Type as ArrowPrimitiveType>::Native> { |
1207 | 0 | let prior = Date64Type::to_naive_date_opt(date)?; |
1208 | 0 | let months = IntervalYearMonthType::to_months(-delta); |
1209 | 0 | let posterior = shift_months(prior, months); |
1210 | 0 | Some(Date64Type::from_naive_date(posterior)) |
1211 | 0 | } |
1212 | | |
1213 | | /// Subtract the given IntervalDayTimeType to an arrow Date64Type |
1214 | | /// |
1215 | | /// # Arguments |
1216 | | /// |
1217 | | /// * `date` - The date on which to perform the operation |
1218 | | /// * `delta` - The interval to subtract |
1219 | | #[deprecated( |
1220 | | since = "56.0.0", |
1221 | | note = "Use `subtract_day_time_opt` instead, which returns an Option to handle overflow." |
1222 | | )] |
1223 | 0 | pub fn subtract_day_time( |
1224 | 0 | date: <Date64Type as ArrowPrimitiveType>::Native, |
1225 | 0 | delta: <IntervalDayTimeType as ArrowPrimitiveType>::Native, |
1226 | 0 | ) -> <Date64Type as ArrowPrimitiveType>::Native { |
1227 | 0 | Self::subtract_day_time_opt(date, delta).unwrap_or_else(|| { |
1228 | 0 | panic!("Date64Type::subtract_day_time overflowed for date: {date}, delta: {delta:?}",) |
1229 | | }) |
1230 | 0 | } |
1231 | | |
1232 | | /// Subtract the given IntervalDayTimeType to an arrow Date64Type |
1233 | | /// |
1234 | | /// # Arguments |
1235 | | /// |
1236 | | /// * `date` - The date on which to perform the operation |
1237 | | /// * `delta` - The interval to subtract |
1238 | | /// |
1239 | | /// Returns `Some(Date64Type)` if it fits, `None` otherwise. |
1240 | 0 | pub fn subtract_day_time_opt( |
1241 | 0 | date: <Date64Type as ArrowPrimitiveType>::Native, |
1242 | 0 | delta: <IntervalDayTimeType as ArrowPrimitiveType>::Native, |
1243 | 0 | ) -> Option<<Date64Type as ArrowPrimitiveType>::Native> { |
1244 | 0 | let (days, ms) = IntervalDayTimeType::to_parts(delta); |
1245 | 0 | let res = Date64Type::to_naive_date_opt(date)?; |
1246 | 0 | let res = res.checked_sub_signed(Duration::try_days(days as i64)?)?; |
1247 | 0 | let res = res.checked_sub_signed(Duration::try_milliseconds(ms as i64)?)?; |
1248 | 0 | Some(Date64Type::from_naive_date(res)) |
1249 | 0 | } |
1250 | | |
1251 | | /// Subtract the given IntervalMonthDayNanoType to an arrow Date64Type |
1252 | | /// |
1253 | | /// # Arguments |
1254 | | /// |
1255 | | /// * `date` - The date on which to perform the operation |
1256 | | /// * `delta` - The interval to subtract |
1257 | | #[deprecated( |
1258 | | since = "56.0.0", |
1259 | | note = "Use `subtract_month_day_nano_opt` instead, which returns an Option to handle overflow." |
1260 | | )] |
1261 | 0 | pub fn subtract_month_day_nano( |
1262 | 0 | date: <Date64Type as ArrowPrimitiveType>::Native, |
1263 | 0 | delta: <IntervalMonthDayNanoType as ArrowPrimitiveType>::Native, |
1264 | 0 | ) -> <Date64Type as ArrowPrimitiveType>::Native { |
1265 | 0 | Self::subtract_month_day_nano_opt(date, delta).unwrap_or_else(|| { |
1266 | 0 | panic!( |
1267 | 0 | "Date64Type::subtract_month_day_nano overflowed for date: {date}, delta: {delta:?}", |
1268 | | ) |
1269 | | }) |
1270 | 0 | } |
1271 | | |
1272 | | /// Subtract the given IntervalMonthDayNanoType to an arrow Date64Type |
1273 | | /// |
1274 | | /// # Arguments |
1275 | | /// |
1276 | | /// * `date` - The date on which to perform the operation |
1277 | | /// * `delta` - The interval to subtract |
1278 | | /// |
1279 | | /// Returns `Some(Date64Type)` if it fits, `None` otherwise. |
1280 | 0 | pub fn subtract_month_day_nano_opt( |
1281 | 0 | date: <Date64Type as ArrowPrimitiveType>::Native, |
1282 | 0 | delta: <IntervalMonthDayNanoType as ArrowPrimitiveType>::Native, |
1283 | 0 | ) -> Option<<Date64Type as ArrowPrimitiveType>::Native> { |
1284 | 0 | let (months, days, nanos) = IntervalMonthDayNanoType::to_parts(delta); |
1285 | 0 | let res = Date64Type::to_naive_date_opt(date)?; |
1286 | 0 | let res = shift_months(res, -months); |
1287 | 0 | let res = res.checked_sub_signed(Duration::try_days(days as i64)?)?; |
1288 | 0 | let res = res.checked_sub_signed(Duration::nanoseconds(nanos))?; |
1289 | 0 | Some(Date64Type::from_naive_date(res)) |
1290 | 0 | } |
1291 | | } |
1292 | | |
1293 | | /// Crate private types for Decimal Arrays |
1294 | | /// |
1295 | | /// Not intended to be used outside this crate |
1296 | | mod decimal { |
1297 | | use super::*; |
1298 | | |
1299 | | pub trait DecimalTypeSealed {} |
1300 | | impl DecimalTypeSealed for Decimal32Type {} |
1301 | | impl DecimalTypeSealed for Decimal64Type {} |
1302 | | impl DecimalTypeSealed for Decimal128Type {} |
1303 | | impl DecimalTypeSealed for Decimal256Type {} |
1304 | | } |
1305 | | |
1306 | | /// A trait over the decimal types, used by [`PrimitiveArray`] to provide a generic |
1307 | | /// implementation across the various decimal types |
1308 | | /// |
1309 | | /// Implemented by [`Decimal32Type`], [`Decimal64Type`], [`Decimal128Type`] and [`Decimal256Type`] |
1310 | | /// for [`Decimal32Array`], [`Decimal64Array`], [`Decimal128Array`] and [`Decimal256Array`] respectively |
1311 | | /// |
1312 | | /// [`PrimitiveArray`]: crate::array::PrimitiveArray |
1313 | | /// [`Decimal32Array`]: crate::array::Decimal32Array |
1314 | | /// [`Decimal64Array`]: crate::array::Decimal64Array |
1315 | | /// [`Decimal128Array`]: crate::array::Decimal128Array |
1316 | | /// [`Decimal256Array`]: crate::array::Decimal256Array |
1317 | | pub trait DecimalType: |
1318 | | 'static + Send + Sync + ArrowPrimitiveType + decimal::DecimalTypeSealed |
1319 | | { |
1320 | | /// Width of the type |
1321 | | const BYTE_LENGTH: usize; |
1322 | | /// Maximum number of significant digits |
1323 | | const MAX_PRECISION: u8; |
1324 | | /// Maximum no of digits after the decimal point (note the scale can be negative) |
1325 | | const MAX_SCALE: i8; |
1326 | | /// fn to create its [`DataType`] |
1327 | | const TYPE_CONSTRUCTOR: fn(u8, i8) -> DataType; |
1328 | | /// Default values for [`DataType`] |
1329 | | const DEFAULT_TYPE: DataType; |
1330 | | |
1331 | | /// "Decimal32", "Decimal64", "Decimal128" or "Decimal256", for use in error messages |
1332 | | const PREFIX: &'static str; |
1333 | | |
1334 | | /// Formats the decimal value with the provided precision and scale |
1335 | | fn format_decimal(value: Self::Native, precision: u8, scale: i8) -> String; |
1336 | | |
1337 | | /// Validates that `value` contains no more than `precision` decimal digits |
1338 | | fn validate_decimal_precision(value: Self::Native, precision: u8) -> Result<(), ArrowError>; |
1339 | | |
1340 | | /// Determines whether `value` contains no more than `precision` decimal digits |
1341 | | fn is_valid_decimal_precision(value: Self::Native, precision: u8) -> bool; |
1342 | | } |
1343 | | |
1344 | | /// Validate that `precision` and `scale` are valid for `T` |
1345 | | /// |
1346 | | /// Returns an Error if: |
1347 | | /// - `precision` is zero |
1348 | | /// - `precision` is larger than `T:MAX_PRECISION` |
1349 | | /// - `scale` is larger than `T::MAX_SCALE` |
1350 | | /// - `scale` is > `precision` |
1351 | 64 | pub fn validate_decimal_precision_and_scale<T: DecimalType>( |
1352 | 64 | precision: u8, |
1353 | 64 | scale: i8, |
1354 | 64 | ) -> Result<(), ArrowError> { |
1355 | 64 | if precision == 0 { |
1356 | 0 | return Err(ArrowError::InvalidArgumentError(format!( |
1357 | 0 | "precision cannot be 0, has to be between [1, {}]", |
1358 | 0 | T::MAX_PRECISION |
1359 | 0 | ))); |
1360 | 64 | } |
1361 | 64 | if precision > T::MAX_PRECISION { |
1362 | 0 | return Err(ArrowError::InvalidArgumentError(format!( |
1363 | 0 | "precision {} is greater than max {}", |
1364 | 0 | precision, |
1365 | 0 | T::MAX_PRECISION |
1366 | 0 | ))); |
1367 | 64 | } |
1368 | 64 | if scale > T::MAX_SCALE { |
1369 | 0 | return Err(ArrowError::InvalidArgumentError(format!( |
1370 | 0 | "scale {} is greater than max {}", |
1371 | 0 | scale, |
1372 | 0 | T::MAX_SCALE |
1373 | 0 | ))); |
1374 | 64 | } |
1375 | 64 | if scale > 0 && scale as u8 > precision { |
1376 | 0 | return Err(ArrowError::InvalidArgumentError(format!( |
1377 | 0 | "scale {scale} is greater than precision {precision}" |
1378 | 0 | ))); |
1379 | 64 | } |
1380 | | |
1381 | 64 | Ok(()) |
1382 | 64 | } |
1383 | | |
1384 | | /// The decimal type for a Decimal32Array |
1385 | | #[derive(Debug)] |
1386 | | pub struct Decimal32Type {} |
1387 | | |
1388 | | impl DecimalType for Decimal32Type { |
1389 | | const BYTE_LENGTH: usize = 4; |
1390 | | const MAX_PRECISION: u8 = DECIMAL32_MAX_PRECISION; |
1391 | | const MAX_SCALE: i8 = DECIMAL32_MAX_SCALE; |
1392 | | const TYPE_CONSTRUCTOR: fn(u8, i8) -> DataType = DataType::Decimal32; |
1393 | | const DEFAULT_TYPE: DataType = |
1394 | | DataType::Decimal32(DECIMAL32_MAX_PRECISION, DECIMAL32_DEFAULT_SCALE); |
1395 | | const PREFIX: &'static str = "Decimal32"; |
1396 | | |
1397 | 0 | fn format_decimal(value: Self::Native, precision: u8, scale: i8) -> String { |
1398 | 0 | format_decimal_str(&value.to_string(), precision as usize, scale) |
1399 | 0 | } |
1400 | | |
1401 | 0 | fn validate_decimal_precision(num: i32, precision: u8) -> Result<(), ArrowError> { |
1402 | 0 | validate_decimal32_precision(num, precision) |
1403 | 0 | } |
1404 | | |
1405 | 0 | fn is_valid_decimal_precision(value: Self::Native, precision: u8) -> bool { |
1406 | 0 | is_validate_decimal32_precision(value, precision) |
1407 | 0 | } |
1408 | | } |
1409 | | |
1410 | | impl ArrowPrimitiveType for Decimal32Type { |
1411 | | type Native = i32; |
1412 | | |
1413 | | const DATA_TYPE: DataType = <Self as DecimalType>::DEFAULT_TYPE; |
1414 | | } |
1415 | | |
1416 | | impl primitive::PrimitiveTypeSealed for Decimal32Type {} |
1417 | | |
1418 | | /// The decimal type for a Decimal64Array |
1419 | | #[derive(Debug)] |
1420 | | pub struct Decimal64Type {} |
1421 | | |
1422 | | impl DecimalType for Decimal64Type { |
1423 | | const BYTE_LENGTH: usize = 8; |
1424 | | const MAX_PRECISION: u8 = DECIMAL64_MAX_PRECISION; |
1425 | | const MAX_SCALE: i8 = DECIMAL64_MAX_SCALE; |
1426 | | const TYPE_CONSTRUCTOR: fn(u8, i8) -> DataType = DataType::Decimal64; |
1427 | | const DEFAULT_TYPE: DataType = |
1428 | | DataType::Decimal64(DECIMAL64_MAX_PRECISION, DECIMAL64_DEFAULT_SCALE); |
1429 | | const PREFIX: &'static str = "Decimal64"; |
1430 | | |
1431 | 0 | fn format_decimal(value: Self::Native, precision: u8, scale: i8) -> String { |
1432 | 0 | format_decimal_str(&value.to_string(), precision as usize, scale) |
1433 | 0 | } |
1434 | | |
1435 | 0 | fn validate_decimal_precision(num: i64, precision: u8) -> Result<(), ArrowError> { |
1436 | 0 | validate_decimal64_precision(num, precision) |
1437 | 0 | } |
1438 | | |
1439 | 0 | fn is_valid_decimal_precision(value: Self::Native, precision: u8) -> bool { |
1440 | 0 | is_validate_decimal64_precision(value, precision) |
1441 | 0 | } |
1442 | | } |
1443 | | |
1444 | | impl ArrowPrimitiveType for Decimal64Type { |
1445 | | type Native = i64; |
1446 | | |
1447 | | const DATA_TYPE: DataType = <Self as DecimalType>::DEFAULT_TYPE; |
1448 | | } |
1449 | | |
1450 | | impl primitive::PrimitiveTypeSealed for Decimal64Type {} |
1451 | | |
1452 | | /// The decimal type for a Decimal128Array |
1453 | | #[derive(Debug)] |
1454 | | pub struct Decimal128Type {} |
1455 | | |
1456 | | impl DecimalType for Decimal128Type { |
1457 | | const BYTE_LENGTH: usize = 16; |
1458 | | const MAX_PRECISION: u8 = DECIMAL128_MAX_PRECISION; |
1459 | | const MAX_SCALE: i8 = DECIMAL128_MAX_SCALE; |
1460 | | const TYPE_CONSTRUCTOR: fn(u8, i8) -> DataType = DataType::Decimal128; |
1461 | | const DEFAULT_TYPE: DataType = |
1462 | | DataType::Decimal128(DECIMAL128_MAX_PRECISION, DECIMAL_DEFAULT_SCALE); |
1463 | | const PREFIX: &'static str = "Decimal128"; |
1464 | | |
1465 | 6 | fn format_decimal(value: Self::Native, precision: u8, scale: i8) -> String { |
1466 | 6 | format_decimal_str(&value.to_string(), precision as usize, scale) |
1467 | 6 | } |
1468 | | |
1469 | 0 | fn validate_decimal_precision(num: i128, precision: u8) -> Result<(), ArrowError> { |
1470 | 0 | validate_decimal_precision(num, precision) |
1471 | 0 | } |
1472 | | |
1473 | 0 | fn is_valid_decimal_precision(value: Self::Native, precision: u8) -> bool { |
1474 | 0 | is_validate_decimal_precision(value, precision) |
1475 | 0 | } |
1476 | | } |
1477 | | |
1478 | | impl ArrowPrimitiveType for Decimal128Type { |
1479 | | type Native = i128; |
1480 | | |
1481 | | const DATA_TYPE: DataType = <Self as DecimalType>::DEFAULT_TYPE; |
1482 | | } |
1483 | | |
1484 | | impl primitive::PrimitiveTypeSealed for Decimal128Type {} |
1485 | | |
1486 | | /// The decimal type for a Decimal256Array |
1487 | | #[derive(Debug)] |
1488 | | pub struct Decimal256Type {} |
1489 | | |
1490 | | impl DecimalType for Decimal256Type { |
1491 | | const BYTE_LENGTH: usize = 32; |
1492 | | const MAX_PRECISION: u8 = DECIMAL256_MAX_PRECISION; |
1493 | | const MAX_SCALE: i8 = DECIMAL256_MAX_SCALE; |
1494 | | const TYPE_CONSTRUCTOR: fn(u8, i8) -> DataType = DataType::Decimal256; |
1495 | | const DEFAULT_TYPE: DataType = |
1496 | | DataType::Decimal256(DECIMAL256_MAX_PRECISION, DECIMAL_DEFAULT_SCALE); |
1497 | | const PREFIX: &'static str = "Decimal256"; |
1498 | | |
1499 | 2 | fn format_decimal(value: Self::Native, precision: u8, scale: i8) -> String { |
1500 | 2 | format_decimal_str(&value.to_string(), precision as usize, scale) |
1501 | 2 | } |
1502 | | |
1503 | 0 | fn validate_decimal_precision(num: i256, precision: u8) -> Result<(), ArrowError> { |
1504 | 0 | validate_decimal256_precision(num, precision) |
1505 | 0 | } |
1506 | | |
1507 | 0 | fn is_valid_decimal_precision(value: Self::Native, precision: u8) -> bool { |
1508 | 0 | is_validate_decimal256_precision(value, precision) |
1509 | 0 | } |
1510 | | } |
1511 | | |
1512 | | impl ArrowPrimitiveType for Decimal256Type { |
1513 | | type Native = i256; |
1514 | | |
1515 | | const DATA_TYPE: DataType = <Self as DecimalType>::DEFAULT_TYPE; |
1516 | | } |
1517 | | |
1518 | | impl primitive::PrimitiveTypeSealed for Decimal256Type {} |
1519 | | |
1520 | 8 | fn format_decimal_str(value_str: &str, precision: usize, scale: i8) -> String { |
1521 | 8 | let (sign, rest) = match value_str.strip_prefix('-') { |
1522 | 4 | Some(stripped) => ("-", stripped), |
1523 | 4 | None => ("", value_str), |
1524 | | }; |
1525 | 8 | let bound = precision.min(rest.len()) + sign.len(); |
1526 | 8 | let value_str = &value_str[0..bound]; |
1527 | | |
1528 | 8 | if scale == 0 { |
1529 | 0 | value_str.to_string() |
1530 | 8 | } else if scale < 0 { |
1531 | 0 | let padding = value_str.len() + scale.unsigned_abs() as usize; |
1532 | 0 | format!("{value_str:0<padding$}") |
1533 | 8 | } else if rest.len() > scale as usize { |
1534 | | // Decimal separator is in the middle of the string |
1535 | 8 | let (whole, decimal) = value_str.split_at(value_str.len() - scale as usize); |
1536 | 8 | format!("{whole}.{decimal}") |
1537 | | } else { |
1538 | | // String has to be padded |
1539 | 0 | format!("{}0.{:0>width$}", sign, rest, width = scale as usize) |
1540 | | } |
1541 | 8 | } |
1542 | | |
1543 | | /// Crate private types for Byte Arrays |
1544 | | /// |
1545 | | /// Not intended to be used outside this crate |
1546 | | pub(crate) mod bytes { |
1547 | | use super::*; |
1548 | | |
1549 | | pub trait ByteArrayTypeSealed {} |
1550 | | impl<O: OffsetSizeTrait> ByteArrayTypeSealed for GenericStringType<O> {} |
1551 | | impl<O: OffsetSizeTrait> ByteArrayTypeSealed for GenericBinaryType<O> {} |
1552 | | |
1553 | | pub trait ByteArrayNativeType: std::fmt::Debug + Send + Sync { |
1554 | | fn from_bytes_checked(b: &[u8]) -> Option<&Self>; |
1555 | | |
1556 | | /// # Safety |
1557 | | /// |
1558 | | /// `b` must be a valid byte sequence for `Self` |
1559 | | unsafe fn from_bytes_unchecked(b: &[u8]) -> &Self; |
1560 | | } |
1561 | | |
1562 | | impl ByteArrayNativeType for [u8] { |
1563 | | #[inline] |
1564 | | fn from_bytes_checked(b: &[u8]) -> Option<&Self> { |
1565 | | Some(b) |
1566 | | } |
1567 | | |
1568 | | #[inline] |
1569 | 94 | unsafe fn from_bytes_unchecked(b: &[u8]) -> &Self { |
1570 | 94 | b |
1571 | 94 | } |
1572 | | } |
1573 | | |
1574 | | impl ByteArrayNativeType for str { |
1575 | | #[inline] |
1576 | | fn from_bytes_checked(b: &[u8]) -> Option<&Self> { |
1577 | | std::str::from_utf8(b).ok() |
1578 | | } |
1579 | | |
1580 | | #[inline] |
1581 | 40 | unsafe fn from_bytes_unchecked(b: &[u8]) -> &Self { |
1582 | 40 | std::str::from_utf8_unchecked(b) |
1583 | 40 | } |
1584 | | } |
1585 | | } |
1586 | | |
1587 | | /// A trait over the variable-size byte array types |
1588 | | /// |
1589 | | /// See [Variable Size Binary Layout](https://arrow.apache.org/docs/format/Columnar.html#variable-size-binary-layout) |
1590 | | pub trait ByteArrayType: 'static + Send + Sync + bytes::ByteArrayTypeSealed { |
1591 | | /// Type of offset i.e i32/i64 |
1592 | | type Offset: OffsetSizeTrait; |
1593 | | /// Type for representing its equivalent rust type i.e |
1594 | | /// Utf8Array will have native type has &str |
1595 | | /// BinaryArray will have type as [u8] |
1596 | | type Native: bytes::ByteArrayNativeType + AsRef<Self::Native> + AsRef<[u8]> + ?Sized; |
1597 | | |
1598 | | /// "Binary" or "String", for use in error messages |
1599 | | const PREFIX: &'static str; |
1600 | | |
1601 | | /// Datatype of array elements |
1602 | | const DATA_TYPE: DataType; |
1603 | | |
1604 | | /// Verifies that every consecutive pair of `offsets` denotes a valid slice of `values` |
1605 | | fn validate(offsets: &OffsetBuffer<Self::Offset>, values: &Buffer) -> Result<(), ArrowError>; |
1606 | | } |
1607 | | |
1608 | | /// [`ByteArrayType`] for string arrays |
1609 | | pub struct GenericStringType<O: OffsetSizeTrait> { |
1610 | | phantom: PhantomData<O>, |
1611 | | } |
1612 | | |
1613 | | impl<O: OffsetSizeTrait> ByteArrayType for GenericStringType<O> { |
1614 | | type Offset = O; |
1615 | | type Native = str; |
1616 | | const PREFIX: &'static str = "String"; |
1617 | | |
1618 | | const DATA_TYPE: DataType = if O::IS_LARGE { |
1619 | | DataType::LargeUtf8 |
1620 | | } else { |
1621 | | DataType::Utf8 |
1622 | | }; |
1623 | | |
1624 | 65 | fn validate(offsets: &OffsetBuffer<Self::Offset>, values: &Buffer) -> Result<(), ArrowError> { |
1625 | | // Verify that the slice as a whole is valid UTF-8 |
1626 | 65 | let validated = std::str::from_utf8(values).map_err(|e| {0 |
1627 | 0 | ArrowError::InvalidArgumentError(format!("Encountered non UTF-8 data: {e}")) |
1628 | 0 | })?; |
1629 | | |
1630 | | // Verify each offset is at a valid character boundary in this UTF-8 array |
1631 | 354 | for offset in offsets65 .iter65 () { |
1632 | 354 | let o = offset.as_usize(); |
1633 | 354 | if !validated.is_char_boundary(o) { |
1634 | 0 | if o < validated.len() { |
1635 | 0 | return Err(ArrowError::InvalidArgumentError(format!( |
1636 | 0 | "Split UTF-8 codepoint at offset {o}" |
1637 | 0 | ))); |
1638 | 0 | } |
1639 | 0 | return Err(ArrowError::InvalidArgumentError(format!( |
1640 | 0 | "Offset of {o} exceeds length of values {}", |
1641 | 0 | validated.len() |
1642 | 0 | ))); |
1643 | 354 | } |
1644 | | } |
1645 | 65 | Ok(()) |
1646 | 65 | } |
1647 | | } |
1648 | | |
1649 | | /// An arrow utf8 array with i32 offsets |
1650 | | pub type Utf8Type = GenericStringType<i32>; |
1651 | | /// An arrow utf8 array with i64 offsets |
1652 | | pub type LargeUtf8Type = GenericStringType<i64>; |
1653 | | |
1654 | | /// [`ByteArrayType`] for binary arrays |
1655 | | pub struct GenericBinaryType<O: OffsetSizeTrait> { |
1656 | | phantom: PhantomData<O>, |
1657 | | } |
1658 | | |
1659 | | impl<O: OffsetSizeTrait> ByteArrayType for GenericBinaryType<O> { |
1660 | | type Offset = O; |
1661 | | type Native = [u8]; |
1662 | | const PREFIX: &'static str = "Binary"; |
1663 | | |
1664 | | const DATA_TYPE: DataType = if O::IS_LARGE { |
1665 | | DataType::LargeBinary |
1666 | | } else { |
1667 | | DataType::Binary |
1668 | | }; |
1669 | | |
1670 | 80 | fn validate(offsets: &OffsetBuffer<Self::Offset>, values: &Buffer) -> Result<(), ArrowError> { |
1671 | | // offsets are guaranteed to be monotonically increasing and non-empty |
1672 | 80 | let max_offset = offsets.last().unwrap().as_usize(); |
1673 | 80 | if values.len() < max_offset { |
1674 | 0 | return Err(ArrowError::InvalidArgumentError(format!( |
1675 | 0 | "Maximum offset of {max_offset} is larger than values of length {}", |
1676 | 0 | values.len() |
1677 | 0 | ))); |
1678 | 80 | } |
1679 | 80 | Ok(()) |
1680 | 80 | } |
1681 | | } |
1682 | | |
1683 | | /// An arrow binary array with i32 offsets |
1684 | | pub type BinaryType = GenericBinaryType<i32>; |
1685 | | /// An arrow binary array with i64 offsets |
1686 | | pub type LargeBinaryType = GenericBinaryType<i64>; |
1687 | | |
1688 | | mod byte_view { |
1689 | | use crate::types::{BinaryViewType, StringViewType}; |
1690 | | |
1691 | | pub trait Sealed: Send + Sync {} |
1692 | | impl Sealed for StringViewType {} |
1693 | | impl Sealed for BinaryViewType {} |
1694 | | } |
1695 | | |
1696 | | /// A trait over the variable length bytes view array types |
1697 | | pub trait ByteViewType: byte_view::Sealed + 'static + PartialEq + Send + Sync { |
1698 | | /// If element in array is utf8 encoded string. |
1699 | | const IS_UTF8: bool; |
1700 | | |
1701 | | /// Datatype of array elements |
1702 | | const DATA_TYPE: DataType = if Self::IS_UTF8 { |
1703 | | DataType::Utf8View |
1704 | | } else { |
1705 | | DataType::BinaryView |
1706 | | }; |
1707 | | |
1708 | | /// "Binary" or "String", for use in displayed or error messages |
1709 | | const PREFIX: &'static str; |
1710 | | |
1711 | | /// Type for representing its equivalent rust type i.e |
1712 | | /// Utf8Array will have native type has &str |
1713 | | /// BinaryArray will have type as [u8] |
1714 | | type Native: bytes::ByteArrayNativeType + AsRef<Self::Native> + AsRef<[u8]> + ?Sized; |
1715 | | |
1716 | | /// Type for owned corresponding to `Native` |
1717 | | type Owned: Debug + Clone + Sync + Send + AsRef<Self::Native>; |
1718 | | |
1719 | | /// Verifies that the provided buffers are valid for this array type |
1720 | | fn validate(views: &[u128], buffers: &[Buffer]) -> Result<(), ArrowError>; |
1721 | | } |
1722 | | |
1723 | | /// [`ByteViewType`] for string arrays |
1724 | | #[derive(PartialEq)] |
1725 | | pub struct StringViewType {} |
1726 | | |
1727 | | impl ByteViewType for StringViewType { |
1728 | | const IS_UTF8: bool = true; |
1729 | | const PREFIX: &'static str = "String"; |
1730 | | |
1731 | | type Native = str; |
1732 | | type Owned = String; |
1733 | | |
1734 | 0 | fn validate(views: &[u128], buffers: &[Buffer]) -> Result<(), ArrowError> { |
1735 | 0 | validate_string_view(views, buffers) |
1736 | 0 | } |
1737 | | } |
1738 | | |
1739 | | /// [`BinaryViewType`] for string arrays |
1740 | | #[derive(PartialEq)] |
1741 | | pub struct BinaryViewType {} |
1742 | | |
1743 | | impl ByteViewType for BinaryViewType { |
1744 | | const IS_UTF8: bool = false; |
1745 | | const PREFIX: &'static str = "Binary"; |
1746 | | type Native = [u8]; |
1747 | | type Owned = Vec<u8>; |
1748 | | |
1749 | 0 | fn validate(views: &[u128], buffers: &[Buffer]) -> Result<(), ArrowError> { |
1750 | 0 | validate_binary_view(views, buffers) |
1751 | 0 | } |
1752 | | } |
1753 | | |
1754 | | #[cfg(test)] |
1755 | | mod tests { |
1756 | | use super::*; |
1757 | | use arrow_data::{layout, BufferSpec}; |
1758 | | |
1759 | | #[test] |
1760 | | fn month_day_nano_should_roundtrip() { |
1761 | | let value = IntervalMonthDayNanoType::make_value(1, 2, 3); |
1762 | | assert_eq!(IntervalMonthDayNanoType::to_parts(value), (1, 2, 3)); |
1763 | | } |
1764 | | |
1765 | | #[test] |
1766 | | fn month_day_nano_should_roundtrip_neg() { |
1767 | | let value = IntervalMonthDayNanoType::make_value(-1, -2, -3); |
1768 | | assert_eq!(IntervalMonthDayNanoType::to_parts(value), (-1, -2, -3)); |
1769 | | } |
1770 | | |
1771 | | #[test] |
1772 | | fn day_time_should_roundtrip() { |
1773 | | let value = IntervalDayTimeType::make_value(1, 2); |
1774 | | assert_eq!(IntervalDayTimeType::to_parts(value), (1, 2)); |
1775 | | } |
1776 | | |
1777 | | #[test] |
1778 | | fn day_time_should_roundtrip_neg() { |
1779 | | let value = IntervalDayTimeType::make_value(-1, -2); |
1780 | | assert_eq!(IntervalDayTimeType::to_parts(value), (-1, -2)); |
1781 | | } |
1782 | | |
1783 | | #[test] |
1784 | | fn year_month_should_roundtrip() { |
1785 | | let value = IntervalYearMonthType::make_value(1, 2); |
1786 | | assert_eq!(IntervalYearMonthType::to_months(value), 14); |
1787 | | } |
1788 | | |
1789 | | #[test] |
1790 | | fn year_month_should_roundtrip_neg() { |
1791 | | let value = IntervalYearMonthType::make_value(-1, -2); |
1792 | | assert_eq!(IntervalYearMonthType::to_months(value), -14); |
1793 | | } |
1794 | | |
1795 | | fn test_layout<T: ArrowPrimitiveType>() { |
1796 | | let layout = layout(&T::DATA_TYPE); |
1797 | | |
1798 | | assert_eq!(layout.buffers.len(), 1); |
1799 | | |
1800 | | let spec = &layout.buffers[0]; |
1801 | | assert_eq!( |
1802 | | spec, |
1803 | | &BufferSpec::FixedWidth { |
1804 | | byte_width: std::mem::size_of::<T::Native>(), |
1805 | | alignment: std::mem::align_of::<T::Native>(), |
1806 | | } |
1807 | | ); |
1808 | | } |
1809 | | |
1810 | | #[test] |
1811 | | fn test_layouts() { |
1812 | | test_layout::<Int8Type>(); |
1813 | | test_layout::<Int16Type>(); |
1814 | | test_layout::<Int32Type>(); |
1815 | | test_layout::<Int64Type>(); |
1816 | | test_layout::<UInt8Type>(); |
1817 | | test_layout::<UInt16Type>(); |
1818 | | test_layout::<UInt32Type>(); |
1819 | | test_layout::<UInt64Type>(); |
1820 | | test_layout::<Float16Type>(); |
1821 | | test_layout::<Float32Type>(); |
1822 | | test_layout::<Float64Type>(); |
1823 | | test_layout::<Decimal32Type>(); |
1824 | | test_layout::<Decimal64Type>(); |
1825 | | test_layout::<Decimal128Type>(); |
1826 | | test_layout::<Decimal256Type>(); |
1827 | | test_layout::<TimestampNanosecondType>(); |
1828 | | test_layout::<TimestampMillisecondType>(); |
1829 | | test_layout::<TimestampMicrosecondType>(); |
1830 | | test_layout::<TimestampNanosecondType>(); |
1831 | | test_layout::<TimestampSecondType>(); |
1832 | | test_layout::<Date32Type>(); |
1833 | | test_layout::<Date64Type>(); |
1834 | | test_layout::<Time32SecondType>(); |
1835 | | test_layout::<Time32MillisecondType>(); |
1836 | | test_layout::<Time64MicrosecondType>(); |
1837 | | test_layout::<Time64NanosecondType>(); |
1838 | | test_layout::<IntervalMonthDayNanoType>(); |
1839 | | test_layout::<IntervalDayTimeType>(); |
1840 | | test_layout::<IntervalYearMonthType>(); |
1841 | | test_layout::<DurationNanosecondType>(); |
1842 | | test_layout::<DurationMicrosecondType>(); |
1843 | | test_layout::<DurationMillisecondType>(); |
1844 | | test_layout::<DurationSecondType>(); |
1845 | | } |
1846 | | } |