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