1use std::{any::type_name, result::Result as StdResult};
5
6use arrow_array::{
7 Array, ArrayRef, BooleanArray, Date32Array, Decimal128Array, Decimal256Array, FixedSizeBinaryArray,
8 Float32Array, Float64Array, Int8Array, Int16Array, Int32Array, Int64Array, IntervalMonthDayNanoArray,
9 LargeBinaryArray, LargeStringArray, NullArray, Time64NanosecondArray, TimestampNanosecondArray, UInt8Array,
10 UInt16Array, UInt32Array, UInt64Array,
11};
12use arrow_buffer::NullBuffer;
13use arrow_schema::{Field, FieldRef};
14
15use crate::{
16 Result,
17 error::{ColumnReadReason, Error, TypeError},
18 util::float_format::{format_f32, format_f64},
19 value::{
20 Value,
21 constraint::bytes::MaxBytes,
22 container::{
23 any_array, bool_array,
24 decimal_array::{DecimalView, checked_decimal_at, decimal_as_string, decimal_get_value},
25 dictionary_array, digest_array, primitive,
26 temporal_array::{self, dates, datetimes, durations, times},
27 uuid_array::{self, identity_ids, uuid4s, uuid7s},
28 varlen_array::{self, blob_as_string, blob_get_value, utf8_as_string, utf8_get_value},
29 wide_int_array::{self, wide_at},
30 },
31 date::Date,
32 datetime::DateTime,
33 decimal::Decimal,
34 dictionary::DictionaryId,
35 duration::Duration,
36 identity::IdentityId,
37 time::Time,
38 uuid::{Uuid4, Uuid7},
39 value_type::{
40 ValueType,
41 field::{field_error, from_field},
42 },
43 },
44};
45
46#[derive(Clone, Debug)]
47pub enum ViewData<'a> {
48 Bool(&'a BooleanArray),
49 Float4(&'a Float32Array),
50 Float8(&'a Float64Array),
51 Int1(&'a Int8Array),
52 Int2(&'a Int16Array),
53 Int4(&'a Int32Array),
54 Int8(&'a Int64Array),
55 Int16(&'a FixedSizeBinaryArray),
56 Uint1(&'a UInt8Array),
57 Uint2(&'a UInt16Array),
58 Uint4(&'a UInt32Array),
59 Uint8(&'a UInt64Array),
60 Uint16(&'a FixedSizeBinaryArray),
61 Utf8 {
62 container: &'a LargeStringArray,
63 max_bytes: MaxBytes,
64 },
65 Date(&'a Date32Array),
66 DateTime(&'a TimestampNanosecondArray),
67 Time(&'a Time64NanosecondArray),
68 Duration(&'a IntervalMonthDayNanoArray),
69 IdentityId(&'a FixedSizeBinaryArray),
70 Uuid4(&'a FixedSizeBinaryArray),
71 Uuid7(&'a FixedSizeBinaryArray),
72 Blob {
73 container: &'a LargeBinaryArray,
74 max_bytes: MaxBytes,
75 },
76 Decimal(DecimalView<'a>),
77 Any {
78 container: &'a LargeBinaryArray,
79 declared_type: Option<ValueType>,
80 },
81 DictionaryId {
82 container: &'a FixedSizeBinaryArray,
83 dictionary_id: Option<DictionaryId>,
84 },
85 Digest {
86 container: &'a LargeBinaryArray,
87 inner: ValueType,
88 accuracy: u32,
89 },
90 None {
91 array: &'a NullArray,
92 },
93}
94
95#[derive(Clone, Debug)]
96pub struct ColumnView<'a> {
97 pub data: ViewData<'a>,
98 pub field: &'a Field,
99}
100
101impl<'a> TryFrom<(&'a ArrayRef, &'a Field)> for ColumnView<'a> {
102 type Error = Error;
103
104 fn try_from((array, field): (&'a ArrayRef, &'a Field)) -> Result<Self> {
105 if array.data_type() != field.data_type() {
106 return Err(field_error(format!(
107 "column {} holds arrow type {}, but its field says {}",
108 field.name(),
109 array.data_type(),
110 field.data_type()
111 )));
112 }
113 Ok(ColumnView {
114 data: view_data(array, field)?,
115 field,
116 })
117 }
118}
119
120impl<'a> TryFrom<&'a (FieldRef, ArrayRef)> for ColumnView<'a> {
121 type Error = Error;
122
123 fn try_from((field, array): &'a (FieldRef, ArrayRef)) -> Result<Self> {
124 ColumnView::try_from((array, field.as_ref()))
125 }
126}
127
128fn view_data<'a>(array: &'a ArrayRef, field: &'a Field) -> Result<ViewData<'a>> {
129 let field_type = from_field(field)?;
130 let Some(value_type) = field_type.value_type else {
131 return Ok(ViewData::None {
132 array: downcast(array, field)?,
133 });
134 };
135 let bare = match value_type {
136 ValueType::Option(inner) => *inner,
137 other => other,
138 };
139 Ok(match bare {
140 ValueType::Boolean => ViewData::Bool(downcast(array, field)?),
141 ValueType::Float4 => ViewData::Float4(downcast(array, field)?),
142 ValueType::Float8 => ViewData::Float8(downcast(array, field)?),
143 ValueType::Int1 => ViewData::Int1(downcast(array, field)?),
144 ValueType::Int2 => ViewData::Int2(downcast(array, field)?),
145 ValueType::Int4 => ViewData::Int4(downcast(array, field)?),
146 ValueType::Int8 => ViewData::Int8(downcast(array, field)?),
147 ValueType::Int16 => ViewData::Int16(downcast(array, field)?),
148 ValueType::Uint1 => ViewData::Uint1(downcast(array, field)?),
149 ValueType::Uint2 => ViewData::Uint2(downcast(array, field)?),
150 ValueType::Uint4 => ViewData::Uint4(downcast(array, field)?),
151 ValueType::Uint8 => ViewData::Uint8(downcast(array, field)?),
152 ValueType::Uint16 => ViewData::Uint16(downcast(array, field)?),
153 ValueType::Utf8 => ViewData::Utf8 {
154 container: downcast(array, field)?,
155 max_bytes: field_type.max_bytes.unwrap_or(MaxBytes::MAX),
156 },
157 ValueType::Date => ViewData::Date(downcast(array, field)?),
158 ValueType::DateTime => ViewData::DateTime(downcast(array, field)?),
159 ValueType::Time => ViewData::Time(downcast(array, field)?),
160 ValueType::Duration => ViewData::Duration(downcast(array, field)?),
161 ValueType::IdentityId => ViewData::IdentityId(downcast(array, field)?),
162 ValueType::Uuid4 => ViewData::Uuid4(downcast(array, field)?),
163 ValueType::Uuid7 => ViewData::Uuid7(downcast(array, field)?),
164 ValueType::Blob => ViewData::Blob {
165 container: downcast(array, field)?,
166 max_bytes: field_type.max_bytes.unwrap_or(MaxBytes::MAX),
167 },
168 ValueType::Decimal {
169 ..
170 } => match array.as_any().downcast_ref::<Decimal128Array>() {
171 Some(container) => ViewData::Decimal(DecimalView::Decimal128(container)),
172 None => ViewData::Decimal(DecimalView::Decimal256(downcast::<Decimal256Array>(array, field)?)),
173 },
174 ValueType::Any | ValueType::List(_) | ValueType::Record(_) | ValueType::Tuple(_) => ViewData::Any {
175 container: downcast(array, field)?,
176 declared_type: field_type.declared_type,
177 },
178 ValueType::DictionaryId => ViewData::DictionaryId {
179 container: downcast(array, field)?,
180 dictionary_id: field_type.dictionary_id,
181 },
182 ValueType::Digest {
183 inner,
184 accuracy,
185 } => ViewData::Digest {
186 container: downcast(array, field)?,
187 inner: *inner,
188 accuracy,
189 },
190 ValueType::Option(_) => {
191 return Err(field_error(format!("column {} has a nested Option type", field.name())));
192 }
193 })
194}
195
196fn downcast<'a, T: 'static>(array: &'a ArrayRef, field: &Field) -> Result<&'a T> {
197 array.as_any().downcast_ref::<T>().ok_or_else(|| {
198 field_error(format!(
199 "column {} holds arrow type {}, which is not a {}",
200 field.name(),
201 array.data_type(),
202 type_name::<T>()
203 ))
204 })
205}
206
207pub trait FromColumnView: Sized {
208 fn from_column_view(view: &ColumnView<'_>, index: usize) -> StdResult<Option<Self>, ColumnReadReason>;
209}
210
211pub trait AsSlice<'a, T> {
212 fn as_slice(&self) -> &'a [T];
213}
214
215impl<'a> ColumnView<'a> {
216 pub fn array(&self) -> &'a dyn Array {
217 match &self.data {
218 ViewData::Bool(a) => *a,
219 ViewData::Float4(a) => *a,
220 ViewData::Float8(a) => *a,
221 ViewData::Int1(a) => *a,
222 ViewData::Int2(a) => *a,
223 ViewData::Int4(a) => *a,
224 ViewData::Int8(a) => *a,
225 ViewData::Int16(a) => *a,
226 ViewData::Uint1(a) => *a,
227 ViewData::Uint2(a) => *a,
228 ViewData::Uint4(a) => *a,
229 ViewData::Uint8(a) => *a,
230 ViewData::Uint16(a) => *a,
231 ViewData::Utf8 {
232 container,
233 ..
234 } => *container,
235 ViewData::Date(a) => *a,
236 ViewData::DateTime(a) => *a,
237 ViewData::Time(a) => *a,
238 ViewData::Duration(a) => *a,
239 ViewData::IdentityId(a) => *a,
240 ViewData::Uuid4(a) => *a,
241 ViewData::Uuid7(a) => *a,
242 ViewData::Blob {
243 container,
244 ..
245 } => *container,
246 ViewData::Decimal(d) => d.array(),
247 ViewData::Any {
248 container,
249 ..
250 } => *container,
251 ViewData::DictionaryId {
252 container,
253 ..
254 } => *container,
255 ViewData::Digest {
256 container,
257 ..
258 } => *container,
259 ViewData::None {
260 array,
261 } => *array,
262 }
263 }
264
265 pub fn len(&self) -> usize {
266 self.array().len()
267 }
268
269 pub fn is_empty(&self) -> bool {
270 self.len() == 0
271 }
272
273 pub fn is_nullable(&self) -> bool {
274 self.field.is_nullable()
275 }
276
277 pub fn logical_nulls(&self) -> Option<NullBuffer> {
278 self.array().logical_nulls()
279 }
280
281 pub fn none_count(&self) -> usize {
282 self.array().logical_null_count()
283 }
284
285 pub fn none_at(&self, index: usize) -> bool {
286 match &self.data {
287 ViewData::None {
288 ..
289 } => true,
290 _ => self.logical_nulls().is_some_and(|nulls| !(index < nulls.len() && nulls.is_valid(index))),
291 }
292 }
293
294 pub fn base_type(&self) -> ValueType {
295 match &self.data {
296 ViewData::Bool(_) => ValueType::Boolean,
297 ViewData::Float4(_) => ValueType::Float4,
298 ViewData::Float8(_) => ValueType::Float8,
299 ViewData::Int1(_) => ValueType::Int1,
300 ViewData::Int2(_) => ValueType::Int2,
301 ViewData::Int4(_) => ValueType::Int4,
302 ViewData::Int8(_) => ValueType::Int8,
303 ViewData::Int16(_) => ValueType::Int16,
304 ViewData::Uint1(_) => ValueType::Uint1,
305 ViewData::Uint2(_) => ValueType::Uint2,
306 ViewData::Uint4(_) => ValueType::Uint4,
307 ViewData::Uint8(_) => ValueType::Uint8,
308 ViewData::Uint16(_) => ValueType::Uint16,
309 ViewData::Utf8 {
310 ..
311 } => ValueType::Utf8,
312 ViewData::Date(_) => ValueType::Date,
313 ViewData::DateTime(_) => ValueType::DateTime,
314 ViewData::Time(_) => ValueType::Time,
315 ViewData::Duration(_) => ValueType::Duration,
316 ViewData::IdentityId(_) => ValueType::IdentityId,
317 ViewData::Uuid4(_) => ValueType::Uuid4,
318 ViewData::Uuid7(_) => ValueType::Uuid7,
319 ViewData::Blob {
320 ..
321 } => ValueType::Blob,
322 ViewData::Decimal(d) => ValueType::decimal(d.precision(), d.scale()),
323 ViewData::Any {
324 declared_type,
325 ..
326 } => declared_type.clone().unwrap_or(ValueType::Any),
327 ViewData::DictionaryId {
328 ..
329 } => ValueType::DictionaryId,
330 ViewData::Digest {
331 inner,
332 accuracy,
333 ..
334 } => ValueType::Digest {
335 inner: Box::new(inner.clone()),
336 accuracy: *accuracy,
337 },
338 ViewData::None {
339 ..
340 } => ValueType::Any,
341 }
342 }
343
344 pub fn get_type(&self) -> ValueType {
345 match self.is_nullable() {
346 true => ValueType::Option(Box::new(self.base_type())),
347 false => self.base_type(),
348 }
349 }
350
351 pub fn is_defined(&self, index: usize) -> bool {
352 if self.none_at(index) {
353 return false;
354 }
355 match &self.data {
356 ViewData::Digest {
357 container,
358 ..
359 } => digest_array::is_defined(container, index),
360 ViewData::None {
361 ..
362 } => false,
363 _ => index < self.len(),
364 }
365 }
366
367 pub fn is_none(&self) -> bool {
368 matches!(self.data, ViewData::None { .. })
369 }
370
371 pub fn is_untyped_none(&self) -> bool {
372 match &self.data {
373 ViewData::None {
374 ..
375 } => true,
376 ViewData::Any {
377 declared_type: None,
378 ..
379 } => self.logical_nulls().is_some_and(|nulls| nulls.null_count() == nulls.len()),
380 _ => false,
381 }
382 }
383
384 pub fn is_bool(&self) -> bool {
385 self.get_type() == ValueType::Boolean
386 }
387
388 pub fn is_utf8(&self) -> bool {
389 self.get_type() == ValueType::Utf8
390 }
391
392 pub fn is_number(&self) -> bool {
393 matches!(
394 self.get_type(),
395 ValueType::Float4
396 | ValueType::Float8 | ValueType::Int1
397 | ValueType::Int2 | ValueType::Int4
398 | ValueType::Int8 | ValueType::Int16
399 | ValueType::Uint1 | ValueType::Uint2
400 | ValueType::Uint4 | ValueType::Uint8
401 | ValueType::Uint16 | ValueType::Decimal { .. }
402 )
403 }
404
405 pub fn is_text(&self) -> bool {
406 self.get_type() == ValueType::Utf8
407 }
408
409 pub fn is_temporal(&self) -> bool {
410 matches!(self.get_type(), ValueType::Date | ValueType::DateTime | ValueType::Time | ValueType::Duration)
411 }
412
413 pub fn is_uuid(&self) -> bool {
414 matches!(self.get_type(), ValueType::Uuid4 | ValueType::Uuid7)
415 }
416
417 pub fn get_value(&self, index: usize) -> Value {
418 if self.none_at(index) {
419 return Value::None {
420 inner: self.base_type(),
421 };
422 }
423 match &self.data {
424 ViewData::Bool(a) => bool_array::get_value(a, index),
425 ViewData::Float4(a) => primitive::get_value(*a, index),
426 ViewData::Float8(a) => primitive::get_value(*a, index),
427 ViewData::Int1(a) => primitive::get_value(*a, index),
428 ViewData::Int2(a) => primitive::get_value(*a, index),
429 ViewData::Int4(a) => primitive::get_value(*a, index),
430 ViewData::Int8(a) => primitive::get_value(*a, index),
431 ViewData::Int16(a) => wide_int_array::get_value::<i128>(a, index),
432 ViewData::Uint1(a) => primitive::get_value(*a, index),
433 ViewData::Uint2(a) => primitive::get_value(*a, index),
434 ViewData::Uint4(a) => primitive::get_value(*a, index),
435 ViewData::Uint8(a) => primitive::get_value(*a, index),
436 ViewData::Uint16(a) => wide_int_array::get_value::<u128>(a, index),
437 ViewData::Utf8 {
438 container,
439 ..
440 } => utf8_get_value(container, index),
441 ViewData::Date(a) => temporal_array::get_value(dates(a), index),
442 ViewData::DateTime(a) => temporal_array::get_value(datetimes(a), index),
443 ViewData::Time(a) => temporal_array::get_value(times(a), index),
444 ViewData::Duration(a) => temporal_array::get_value(durations(a), index),
445 ViewData::IdentityId(a) => uuid_array::identity_id_get_value(identity_ids(a), index),
446 ViewData::Uuid4(a) => uuid_array::get_value(uuid4s(a), index),
447 ViewData::Uuid7(a) => uuid_array::get_value(uuid7s(a), index),
448 ViewData::Blob {
449 container,
450 ..
451 } => blob_get_value(container, index),
452 ViewData::Decimal(d) => decimal_get_value(d, index),
453 ViewData::Any {
454 container,
455 declared_type,
456 } => any_array::get_value(container, declared_type.as_ref(), index),
457 ViewData::DictionaryId {
458 container,
459 ..
460 } => dictionary_array::get_value(container, index),
461 ViewData::Digest {
462 container,
463 ..
464 } => digest_array::get_value(container, index),
465 ViewData::None {
466 ..
467 } => Value::none(),
468 }
469 }
470
471 pub fn values(&self) -> Vec<Value> {
472 let none = Value::None {
473 inner: self.base_type(),
474 };
475 let len = self.len();
476 let nulls = self.logical_nulls();
477 let defined =
478 |index: usize| nulls.as_ref().is_none_or(|nulls| index < nulls.len() && nulls.is_valid(index));
479 macro_rules! collect {
480 ($get:expr) => {
481 (0..len).map(|index| {
482 if defined(index) {
483 $get(index)
484 } else {
485 none.clone()
486 }
487 })
488 .collect()
489 };
490 }
491 match &self.data {
492 ViewData::Bool(a) => collect!(|i| bool_array::get_value(a, i)),
493 ViewData::Float4(a) => collect!(|i| primitive::get_value(*a, i)),
494 ViewData::Float8(a) => collect!(|i| primitive::get_value(*a, i)),
495 ViewData::Int1(a) => collect!(|i| primitive::get_value(*a, i)),
496 ViewData::Int2(a) => collect!(|i| primitive::get_value(*a, i)),
497 ViewData::Int4(a) => collect!(|i| primitive::get_value(*a, i)),
498 ViewData::Int8(a) => collect!(|i| primitive::get_value(*a, i)),
499 ViewData::Int16(a) => collect!(|i| wide_int_array::get_value::<i128>(a, i)),
500 ViewData::Uint1(a) => collect!(|i| primitive::get_value(*a, i)),
501 ViewData::Uint2(a) => collect!(|i| primitive::get_value(*a, i)),
502 ViewData::Uint4(a) => collect!(|i| primitive::get_value(*a, i)),
503 ViewData::Uint8(a) => collect!(|i| primitive::get_value(*a, i)),
504 ViewData::Uint16(a) => collect!(|i| wide_int_array::get_value::<u128>(a, i)),
505 ViewData::Utf8 {
506 container,
507 ..
508 } => collect!(|i| utf8_get_value(container, i)),
509 ViewData::Date(a) => {
510 let values = dates(a);
511 collect!(|i| temporal_array::get_value(values, i))
512 }
513 ViewData::DateTime(a) => {
514 let values = datetimes(a);
515 collect!(|i| temporal_array::get_value(values, i))
516 }
517 ViewData::Time(a) => {
518 let values = times(a);
519 collect!(|i| temporal_array::get_value(values, i))
520 }
521 ViewData::Duration(a) => {
522 let values = durations(a);
523 collect!(|i| temporal_array::get_value(values, i))
524 }
525 ViewData::IdentityId(a) => {
526 let values = identity_ids(a);
527 collect!(|i| uuid_array::identity_id_get_value(values, i))
528 }
529 ViewData::Uuid4(a) => {
530 let values = uuid4s(a);
531 collect!(|i| uuid_array::get_value(values, i))
532 }
533 ViewData::Uuid7(a) => {
534 let values = uuid7s(a);
535 collect!(|i| uuid_array::get_value(values, i))
536 }
537 ViewData::Blob {
538 container,
539 ..
540 } => collect!(|i| blob_get_value(container, i)),
541 ViewData::Decimal(d) => collect!(|i| decimal_get_value(d, i)),
542 ViewData::Any {
543 container,
544 declared_type,
545 } => collect!(|i| any_array::get_value(container, declared_type.as_ref(), i)),
546 ViewData::DictionaryId {
547 container,
548 ..
549 } => collect!(|i| dictionary_array::get_value(container, i)),
550 ViewData::Digest {
551 container,
552 ..
553 } => collect!(|i| digest_array::get_value(container, i)),
554 ViewData::None {
555 ..
556 } => vec![none; len],
557 }
558 }
559
560 pub fn as_string(&self, index: usize) -> String {
561 if self.none_at(index) {
562 return "none".to_string();
563 }
564 match &self.data {
565 ViewData::Bool(a) => bool_array::as_string(a, index),
566 ViewData::Float4(a) => {
567 a.values().get(index).map_or_else(|| "none".to_string(), |&v| format_f32(v))
568 }
569 ViewData::Float8(a) => {
570 a.values().get(index).map_or_else(|| "none".to_string(), |&v| format_f64(v))
571 }
572 ViewData::Int1(a) => primitive::as_string(*a, index),
573 ViewData::Int2(a) => primitive::as_string(*a, index),
574 ViewData::Int4(a) => primitive::as_string(*a, index),
575 ViewData::Int8(a) => primitive::as_string(*a, index),
576 ViewData::Int16(a) => wide_int_array::as_string::<i128>(a, index),
577 ViewData::Uint1(a) => primitive::as_string(*a, index),
578 ViewData::Uint2(a) => primitive::as_string(*a, index),
579 ViewData::Uint4(a) => primitive::as_string(*a, index),
580 ViewData::Uint8(a) => primitive::as_string(*a, index),
581 ViewData::Uint16(a) => wide_int_array::as_string::<u128>(a, index),
582 ViewData::Utf8 {
583 container,
584 ..
585 } => utf8_as_string(container, index),
586 ViewData::Date(a) => temporal_array::as_string(dates(a), index),
587 ViewData::DateTime(a) => temporal_array::as_string(datetimes(a), index),
588 ViewData::Time(a) => temporal_array::as_string(times(a), index),
589 ViewData::Duration(a) => temporal_array::as_string(durations(a), index),
590 ViewData::IdentityId(a) => uuid_array::as_string(identity_ids(a), index),
591 ViewData::Uuid4(a) => uuid_array::as_string(uuid4s(a), index),
592 ViewData::Uuid7(a) => uuid_array::as_string(uuid7s(a), index),
593 ViewData::Blob {
594 container,
595 ..
596 } => blob_as_string(container, index),
597 ViewData::Decimal(d) => decimal_as_string(d, index),
598 ViewData::Any {
599 container,
600 ..
601 } => any_array::as_string(container, index),
602 ViewData::DictionaryId {
603 container,
604 ..
605 } => dictionary_array::as_string(container, index),
606 ViewData::Digest {
607 container,
608 ..
609 } => digest_array::as_string(container, index),
610 ViewData::None {
611 ..
612 } => "none".to_string(),
613 }
614 }
615
616 pub fn get_as<T: FromColumnView>(&self, index: usize) -> Result<Option<T>> {
617 if self.none_at(index) {
618 return Ok(None);
619 }
620 T::from_column_view(self, index).map_err(|reason| {
621 TypeError::ColumnRead {
622 column_type: self.base_type(),
623 target: type_name::<T>(),
624 reason,
625 }
626 .into()
627 })
628 }
629
630 pub fn get_str(&self, index: usize) -> Option<&'a str> {
631 match &self.data {
632 ViewData::Utf8 {
633 container,
634 ..
635 } if !self.none_at(index) => varlen_array::get(*container, index),
636 _ => None,
637 }
638 }
639
640 pub fn get_bytes(&self, index: usize) -> Option<&'a [u8]> {
641 match &self.data {
642 ViewData::Blob {
643 container,
644 ..
645 } if !self.none_at(index) => varlen_array::get(*container, index),
646 _ => None,
647 }
648 }
649
650 pub fn as_slice<T>(&self) -> &'a [T]
651 where
652 Self: AsSlice<'a, T>,
653 {
654 <Self as AsSlice<'a, T>>::as_slice(self)
655 }
656
657 pub fn iter(&self) -> impl Iterator<Item = Value> + '_ {
658 (0..self.len()).map(move |index| self.get_value(index))
659 }
660}
661
662impl<'a> AsSlice<'a, bool> for ColumnView<'a> {
663 fn as_slice(&self) -> &'a [bool] {
664 match &self.data {
665 ViewData::Bool(_) => {
666 panic!("as_slice() is not supported for BooleanArray. Use to_vec() instead.")
667 }
668 _ => panic!("called `as_slice::<bool>()` on ColumnView::{:?}", self.get_type()),
669 }
670 }
671}
672
673macro_rules! impl_as_slice {
674 ($t:ty, $variant:ident native) => {
675 impl<'a> AsSlice<'a, $t> for ColumnView<'a> {
676 fn as_slice(&self) -> &'a [$t] {
677 match &self.data {
678 ViewData::$variant(array) => array.values(),
679 _ => panic!(
680 "called `as_slice::<{}>()` on ColumnView::{:?}",
681 stringify!($t),
682 self.get_type()
683 ),
684 }
685 }
686 }
687 };
688 ($t:ty, $variant:ident typed $typed:ident) => {
689 impl<'a> AsSlice<'a, $t> for ColumnView<'a> {
690 fn as_slice(&self) -> &'a [$t] {
691 match &self.data {
692 ViewData::$variant(array) => $typed(array),
693 _ => panic!(
694 "called `as_slice::<{}>()` on ColumnView::{:?}",
695 stringify!($t),
696 self.get_type()
697 ),
698 }
699 }
700 }
701 };
702}
703
704impl_as_slice!(f32, Float4 native);
705impl_as_slice!(f64, Float8 native);
706impl_as_slice!(i8, Int1 native);
707impl_as_slice!(i16, Int2 native);
708impl_as_slice!(i32, Int4 native);
709impl_as_slice!(i64, Int8 native);
710impl_as_slice!(u8, Uint1 native);
711impl_as_slice!(u16, Uint2 native);
712impl_as_slice!(u32, Uint4 native);
713impl_as_slice!(u64, Uint8 native);
714impl_as_slice!(Date, Date typed dates);
715impl_as_slice!(DateTime, DateTime typed datetimes);
716impl_as_slice!(Time, Time typed times);
717impl_as_slice!(Duration, Duration typed durations);
718
719fn wrong_type<T>() -> StdResult<Option<T>, ColumnReadReason> {
720 Err(ColumnReadReason::WrongType)
721}
722
723macro_rules! impl_from_column_view_widening {
724 ($($t:ty => [$($variant:ident),*]),* $(,)?) => { $(
725 impl FromColumnView for $t {
726 fn from_column_view(view: &ColumnView<'_>, index: usize) -> StdResult<Option<Self>, ColumnReadReason> {
727 match &view.data {
728 $(ViewData::$variant(c) => Ok(c.values().get(index).map(|&v| <$t>::from(v))),)*
729 _ => wrong_type(),
730 }
731 }
732 }
733 )* };
734}
735
736impl_from_column_view_widening!(
737 i8 => [Int1],
738 i16 => [Int1, Int2],
739 i32 => [Int1, Int2, Int4],
740 i64 => [Int1, Int2, Int4, Int8],
741 u8 => [Uint1],
742 u16 => [Uint1, Uint2],
743 u32 => [Uint1, Uint2, Uint4],
744 u64 => [Uint1, Uint2, Uint4, Uint8],
745 f32 => [Float4],
746 f64 => [Float4, Float8],
747);
748
749impl FromColumnView for i128 {
750 fn from_column_view(view: &ColumnView<'_>, index: usize) -> StdResult<Option<Self>, ColumnReadReason> {
751 match &view.data {
752 ViewData::Int1(c) => Ok(c.values().get(index).map(|&v| i128::from(v))),
753 ViewData::Int2(c) => Ok(c.values().get(index).map(|&v| i128::from(v))),
754 ViewData::Int4(c) => Ok(c.values().get(index).map(|&v| i128::from(v))),
755 ViewData::Int8(c) => Ok(c.values().get(index).map(|&v| i128::from(v))),
756 ViewData::Int16(c) => Ok(wide_at::<i128>(c, index)),
757 _ => wrong_type(),
758 }
759 }
760}
761
762impl FromColumnView for u128 {
763 fn from_column_view(view: &ColumnView<'_>, index: usize) -> StdResult<Option<Self>, ColumnReadReason> {
764 match &view.data {
765 ViewData::Uint1(c) => Ok(c.values().get(index).map(|&v| u128::from(v))),
766 ViewData::Uint2(c) => Ok(c.values().get(index).map(|&v| u128::from(v))),
767 ViewData::Uint4(c) => Ok(c.values().get(index).map(|&v| u128::from(v))),
768 ViewData::Uint8(c) => Ok(c.values().get(index).map(|&v| u128::from(v))),
769 ViewData::Uint16(c) => Ok(wide_at::<u128>(c, index)),
770 _ => wrong_type(),
771 }
772 }
773}
774
775impl FromColumnView for bool {
776 fn from_column_view(view: &ColumnView<'_>, index: usize) -> StdResult<Option<Self>, ColumnReadReason> {
777 match &view.data {
778 ViewData::Bool(c) => Ok((index < c.len()).then(|| c.value(index))),
779 _ => wrong_type(),
780 }
781 }
782}
783
784impl FromColumnView for String {
785 fn from_column_view(view: &ColumnView<'_>, index: usize) -> StdResult<Option<Self>, ColumnReadReason> {
786 match &view.data {
787 ViewData::Utf8 {
788 container,
789 ..
790 } => Ok(varlen_array::get(*container, index).map(str::to_string)),
791 _ => wrong_type(),
792 }
793 }
794}
795
796impl FromColumnView for Vec<u8> {
797 fn from_column_view(view: &ColumnView<'_>, index: usize) -> StdResult<Option<Self>, ColumnReadReason> {
798 match &view.data {
799 ViewData::Blob {
800 container,
801 ..
802 } => Ok(varlen_array::get(*container, index).map(<[u8]>::to_vec)),
803 _ => wrong_type(),
804 }
805 }
806}
807
808impl FromColumnView for Date {
809 fn from_column_view(view: &ColumnView<'_>, index: usize) -> StdResult<Option<Self>, ColumnReadReason> {
810 match &view.data {
811 ViewData::Date(c) => Ok(dates(c).get(index).copied()),
812 _ => wrong_type(),
813 }
814 }
815}
816
817impl FromColumnView for DateTime {
818 fn from_column_view(view: &ColumnView<'_>, index: usize) -> StdResult<Option<Self>, ColumnReadReason> {
819 match &view.data {
820 ViewData::DateTime(c) => Ok(datetimes(c).get(index).copied()),
821 _ => wrong_type(),
822 }
823 }
824}
825
826impl FromColumnView for Time {
827 fn from_column_view(view: &ColumnView<'_>, index: usize) -> StdResult<Option<Self>, ColumnReadReason> {
828 match &view.data {
829 ViewData::Time(c) => Ok(times(c).get(index).copied()),
830 _ => wrong_type(),
831 }
832 }
833}
834
835impl FromColumnView for Duration {
836 fn from_column_view(view: &ColumnView<'_>, index: usize) -> StdResult<Option<Self>, ColumnReadReason> {
837 match &view.data {
838 ViewData::Duration(c) => Ok(durations(c).get(index).copied()),
839 _ => wrong_type(),
840 }
841 }
842}
843
844impl FromColumnView for Uuid4 {
845 fn from_column_view(view: &ColumnView<'_>, index: usize) -> StdResult<Option<Self>, ColumnReadReason> {
846 match &view.data {
847 ViewData::Uuid4(c) => Ok(uuid4s(c).get(index).copied()),
848 _ => wrong_type(),
849 }
850 }
851}
852
853impl FromColumnView for Uuid7 {
854 fn from_column_view(view: &ColumnView<'_>, index: usize) -> StdResult<Option<Self>, ColumnReadReason> {
855 match &view.data {
856 ViewData::Uuid7(c) => Ok(uuid7s(c).get(index).copied()),
857 _ => wrong_type(),
858 }
859 }
860}
861
862impl FromColumnView for Decimal {
863 fn from_column_view(view: &ColumnView<'_>, index: usize) -> StdResult<Option<Self>, ColumnReadReason> {
864 match &view.data {
865 ViewData::Decimal(d) => checked_decimal_at(d, index).ok_or(ColumnReadReason::DoesNotFit),
866 ViewData::Float4(c) => c
867 .values()
868 .get(index)
869 .map(|&v| Decimal::from_f32(v).ok_or(ColumnReadReason::DoesNotFit))
870 .transpose(),
871 ViewData::Float8(c) => c
872 .values()
873 .get(index)
874 .map(|&v| Decimal::from_f64(v).ok_or(ColumnReadReason::DoesNotFit))
875 .transpose(),
876 _ => wrong_type(),
877 }
878 }
879}
880
881impl FromColumnView for IdentityId {
882 fn from_column_view(view: &ColumnView<'_>, index: usize) -> StdResult<Option<Self>, ColumnReadReason> {
883 match &view.data {
884 ViewData::IdentityId(c) => Ok(identity_ids(c).get(index).copied()),
885 _ => wrong_type(),
886 }
887 }
888}