-
Notifications
You must be signed in to change notification settings - Fork 1.2k
[Variant] Add variant_get and Shredded VariantArray
#8021
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 10 commits
3ba9fe0
f458ec5
52cf52b
6b66650
924155c
5cb1068
9c22f85
eee199e
264356b
336a0a3
016cee1
3e8820b
55a7ae6
85e7194
6e38490
0ccd0f8
f8b2df4
2355247
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -17,8 +17,9 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //! [`VariantArray`] implementation | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| use arrow::array::{Array, ArrayData, ArrayRef, AsArray, StructArray}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| use arrow::array::{Array, ArrayData, ArrayRef, AsArray, BinaryViewArray, StructArray}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| use arrow::buffer::NullBuffer; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| use arrow::datatypes::Int32Type; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| use arrow_schema::{ArrowError, DataType}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| use parquet_variant::Variant; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| use std::any::Any; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -44,27 +45,11 @@ use std::sync::Arc; | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// [document]: https://docs.google.com/document/d/1pw0AWoMQY3SjD7R4LgbPvMjG_xSCtXp3rZHkVp9jpZ4/edit?usp=sharing | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[derive(Debug)] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub struct VariantArray { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// StructArray of up to three fields: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// 1. A required field named `metadata` which is binary, large_binary, or | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// binary_view | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// 2. An optional field named `value` that is binary, large_binary, or | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// binary_view | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// 3. An optional field named `typed_value` which can be any primitive type | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// or be a list, large_list, list_view or struct | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// NOTE: It is also permissible for the metadata field to be | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Dictionary-Encoded, preferably (but not required) with an index type of | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// int8. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Reference to the underlying StructArray | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| inner: StructArray, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Reference to the metadata column of inner | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| metadata_ref: ArrayRef, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Reference to the value column of inner | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| value_ref: ArrayRef, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// how is this variant array shredded? | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| shredding_state: ShreddingState, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| impl VariantArray { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -79,12 +64,22 @@ impl VariantArray { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// # Errors: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// - If the `StructArray` does not contain the required fields | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// # Current support | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// This structure does not (yet) support the full Arrow Variant Array specification. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// # Requirements of the `StructArray` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// 1. A required field named `metadata` which is binary, large_binary, or | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// binary_view | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// 2. An optional field named `value` that is binary, large_binary, or | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// binary_view | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// 3. An optional field named `typed_value` which can be any primitive type | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// or be a list, large_list, list_view or struct | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// NOTE: It is also permissible for the metadata field to be | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Dictionary-Encoded, preferably (but not required) with an index type of | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// int8. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Only `StructArrays` with `metadata` and `value` fields that are | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// [`BinaryViewArray`] are supported. Shredded values are not currently supported | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// nor are using types other than `BinaryViewArray` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Currently, only [`BinaryViewArray`] are supported. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// [`BinaryViewArray`]: arrow::array::BinaryViewArray | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub fn try_new(inner: ArrayRef) -> Result<Self, ArrowError> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -93,35 +88,47 @@ impl VariantArray { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "Invalid VariantArray: requires StructArray as input".to_string(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| )); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Ensure the StructArray has a metadata field of BinaryView | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let Some(metadata_field) = VariantArray::find_metadata_field(inner) else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Note the specification allows for any order so we must search by name | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Ensure the StructArray has a metadata field of BinaryView | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let Some(metadata_field) = inner.column_by_name("metadata") else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return Err(ArrowError::InvalidArgumentError( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "Invalid VariantArray: StructArray must contain a 'metadata' field".to_string(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| )); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if metadata_field.data_type() != &DataType::BinaryView { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let Some(metadata) = metadata_field.as_binary_view_opt() else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return Err(ArrowError::NotYetImplemented(format!( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+98
to
99
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. aside: Out of curiosity, do we have any style/preference guidelines for let Some(foo) = foo_opt else {
return Err(...);
};vs. let foo = foo_opt.unwrap_or_else(|| {
...
})?;? The former seems both more direct and less verbose, at least in this case?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I personally prefer this pattern for the reasons you suggest. However, I don't know of anything formal we have discussed or agreed on let Some(foo) = foo_opt else {
return Err(...);
}; |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "VariantArray 'metadata' field must be BinaryView, got {}", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| metadata_field.data_type() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ))); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let Some(value_field) = VariantArray::find_value_field(inner) else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return Err(ArrowError::InvalidArgumentError( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "Invalid VariantArray: StructArray must contain a 'value' field".to_string(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| )); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if value_field.data_type() != &DataType::BinaryView { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return Err(ArrowError::NotYetImplemented(format!( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "VariantArray 'value' field must be BinaryView, got {}", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| value_field.data_type() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ))); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Find the value field, if present | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let value = inner | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .column_by_name("value") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .map(|v| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let Some(binary_view) = v.as_binary_view_opt() else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return Err(ArrowError::NotYetImplemented(format!( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "VariantArray 'value' field must be BinaryView, got {}", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| v.data_type() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ))); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Ok(binary_view) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
alamb marked this conversation as resolved.
Outdated
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .transpose()?; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Find the typed_value field, if present | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let typed_value = inner.column_by_name("typed_value"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Note these clones are cheap, they just bump the ref count | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let inner = inner.clone(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let shredding_state = | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ShreddingState::try_new(metadata.clone(), value.cloned(), typed_value.cloned())?; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Ok(Self { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| inner: inner.clone(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| metadata_ref: metadata_field, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| value_ref: value_field, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| inner, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| shredding_state, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -135,36 +142,195 @@ impl VariantArray { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.inner | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Return the shredding state of this `VariantArray` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub fn shredding_state(&self) -> &ShreddingState { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| &self.shredding_state | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Return the [`Variant`] instance stored at the given row | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Panics if the index is out of bounds. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Consistently with other Arrow arrays types, this API requires you to | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// check for nulls first using [`Self::is_valid`]. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// # Panics | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// * if the index is out of bounds | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// * if the array value is null | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// If this is a shredded variant but has no value at the shredded location, it | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// will return [`Variant::Null`]. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// # Performance Note | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// This is certainly not the most efficient way to access values in a | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// `VariantArray`, but it is useful for testing and debugging. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Note: Does not do deep validation of the [`Variant`], so it is up to the | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// caller to ensure that the metadata and value were constructed correctly. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub fn value(&self, index: usize) -> Variant { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let metadata = self.metadata_field().as_binary_view().value(index); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let value = self.value_field().as_binary_view().value(index); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Variant::new(metadata, value) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| match &self.shredding_state { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ShreddingState::Unshredded { metadata, value } => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Variant::new(metadata.value(index), value.value(index)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ShreddingState::FullyShredded { typed_value, .. } => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if typed_value.is_null(index) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Variant::Null | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| typed_value_to_variant(typed_value, index) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ShreddingState::PartiallyShredded { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| metadata, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| value, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| typed_value, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if typed_value.is_null(index) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Variant::new(metadata.value(index), value.value(index)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| typed_value_to_variant(typed_value, index) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+169
to
+190
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Part of me wonders whether this "shredding state" enum is actually helping, vs. just storing
and (the file should be able to omit both physical columns, in case of a perfectly shredded all-null the logical column)
Suggested change
(this assumes that
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The reason I first introduced the enum was that in Another reason reason was that I ended up with redundant error checking that was in the
I personally think having names for the different shredding types makes working with the code easier, even if all 4 combinations are valid. I think you are right, however, that the shredding spec allows both to be None. I double checked the Arrow Proposal as it also implies both being null is permitted:
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My proposal is to leave the ShreddingState enum in and I will file a follow on ticket to support the
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I guess... but it seems like there's so much code just managing the resulting enum variants that I question whether it's a net win. Like the getters for metadata, value, etc. or the above code that shrinks from 25 lines to seven while handling more cases. Clearly either way can be made correct, tho, so I guess it's a matter of preference.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yeah, I agree it is a matter of preference. If someone else feels strongly, I am not opposed to changing it |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fn find_metadata_field(array: &StructArray) -> Option<ArrayRef> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| array.column_by_name("metadata").cloned() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Return a reference to the metadata field of the [`StructArray`] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub fn metadata_field(&self) -> &BinaryViewArray { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.shredding_state.metadata_field() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fn find_value_field(array: &StructArray) -> Option<ArrayRef> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| array.column_by_name("value").cloned() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Return a reference to the value field of the `StructArray` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub fn value_field(&self) -> Option<&BinaryViewArray> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.shredding_state.value_field() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Return a reference to the metadata field of the [`StructArray`] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub fn metadata_field(&self) -> &ArrayRef { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // spec says fields order is not guaranteed, so we search by name | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| &self.metadata_ref | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Return a reference to the typed_value field of the `StructArray`, if present | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub fn typed_value_field(&self) -> Option<&ArrayRef> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.shredding_state.typed_value_field() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+195
to
+205
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These become trivial if we ditch the |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Return a reference to the value field of the `StructArray` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub fn value_field(&self) -> &ArrayRef { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // spec says fields order is not guaranteed, so we search by name | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| &self.value_ref | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Variant arrays can be shredded in one of three states, encoded here | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #[derive(Debug)] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub enum ShreddingState { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For a future
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am not sure I filed a ticket to track adding AllNull: |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// This variant has no typed_value field | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Unshredded { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| metadata: BinaryViewArray, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| value: BinaryViewArray, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// This variant has a typed_value field and no value field | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// meaning it is fully shredded (aka the value is stored in typed_value) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| FullyShredded { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| metadata: BinaryViewArray, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| typed_value: ArrayRef, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// This variant has both a value field and a typed_value field | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// meaning it is partially shredded: first the typed_value is used, and | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// if that is null, the value field is used. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| PartiallyShredded { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| metadata: BinaryViewArray, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| value: BinaryViewArray, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| typed_value: ArrayRef, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| impl ShreddingState { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// try to create a new `ShreddingState` from the given fields | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub fn try_new( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| metadata: BinaryViewArray, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| value: Option<BinaryViewArray>, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| typed_value: Option<ArrayRef>, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) -> Result<Self, ArrowError> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| match (metadata, value, typed_value) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| (metadata, Some(value), Some(typed_value)) => Ok(Self::PartiallyShredded { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| metadata, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| value, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| typed_value, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| (metadata, Some(value), None) => Ok(Self::Unshredded { metadata, value }), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| (metadata, None, Some(typed_value)) => Ok(Self::FullyShredded { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| metadata, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| typed_value, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| (_metadata_field, None, None) => Err(ArrowError::InvalidArgumentError(String::from( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "VariantArray has neither value nor typed_value field", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+273
to
+274
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm pretty sure the shredding spec allows this case. It corresponds to a perfectly shredded all-null column where the writer chose to omit both of them as unnecessary. (see other comment above)
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Makes sense -- I'll file a follow on ticket to add support
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ))), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Return a reference to the metadata field | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub fn metadata_field(&self) -> &BinaryViewArray { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| match self { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ShreddingState::Unshredded { metadata, .. } => metadata, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ShreddingState::FullyShredded { metadata, .. } => metadata, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ShreddingState::PartiallyShredded { metadata, .. } => metadata, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Return a reference to the value field, if present | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub fn value_field(&self) -> Option<&BinaryViewArray> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| match self { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ShreddingState::Unshredded { value, .. } => Some(value), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ShreddingState::FullyShredded { .. } => None, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ShreddingState::PartiallyShredded { value, .. } => Some(value), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Return a reference to the typed_value field, if present | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub fn typed_value_field(&self) -> Option<&ArrayRef> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| match self { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ShreddingState::Unshredded { .. } => None, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ShreddingState::FullyShredded { typed_value, .. } => Some(typed_value), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ShreddingState::PartiallyShredded { typed_value, .. } => Some(typed_value), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Slice all the underlying arrays | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub fn slice(&self, offset: usize, length: usize) -> Self { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| match self { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ShreddingState::Unshredded { metadata, value } => ShreddingState::Unshredded { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| metadata: metadata.slice(offset, length), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| value: value.slice(offset, length), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ShreddingState::FullyShredded { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| metadata, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| typed_value, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } => ShreddingState::FullyShredded { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| metadata: metadata.slice(offset, length), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| typed_value: typed_value.slice(offset, length), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ShreddingState::PartiallyShredded { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| metadata, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| value, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| typed_value, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } => ShreddingState::PartiallyShredded { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| metadata: metadata.slice(offset, length), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| value: value.slice(offset, length), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| typed_value: typed_value.slice(offset, length), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// returns the non-null element at index as a Variant | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fn typed_value_to_variant(typed_value: &ArrayRef, index: usize) -> Variant { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Suggest to make this return
Suggested change
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. other Arrow Array apis don't return /// Consistently with other Arrow arrays types, this API requires you to
/// check for nulls first using [`Self::is_valid`].
I think the reason it to allow a better chance at LLVM vectorizing the code, which I don't think is likely relevant here. We could make the Variant API deviate from this pattern (it is already different in several other ways) and return
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
For public API -- 100% agree. This is a private internal API tho, so it seems like we have room to do what we think makes the code simple/maintainable. Pulling important work inside the method instead of requiring all callers to remember it seems like a good example of that. We can always change it if we discover it hurts performance or readability.
AFAIK, arrow normally requires all array entries to be physically valid, even when logically null. That way, one can perform columnar operations blindly and then just use the null masks to ignore the unwanted values after the fact. Here, we're accessing
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Sorry -- I wasn't clear -- the reason I was talking about
Yeah I agree I don't think it will make any difference for performance with Cariants. The primary reason in my mind is to be consistent with other APIs. I think in an earlier version of this PR I actually had changed |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| match typed_value.data_type() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| DataType::Int32 => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let typed_value = typed_value.as_primitive::<Int32Type>(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Variant::from(typed_value.value(index)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+335
to
+338
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good use for downcast_primitive_array macro?
Suggested change
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I couldn't make that work as it needs more information than just the native type (e.g. the precision/scale for decimals). @superserious-dev 's |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // todo other types here (note this is very similar to cast_to_variant.rs) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // so it would be great to figure out how to share this code | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| _ => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // We shouldn't panic in production code, but this is a | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // placeholder until we implement more types | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // TODO tickets: XXXX | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| debug_assert!( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| false, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "Unsupported typed_value type: {:?}", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| typed_value.data_type() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Variant::Null | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+311
to
354
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This could be useful as a (public) function on its own. For example, this could be used to cast columns to variant like in
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a great idea -- I am working to pull it into its own cast_to_variant function
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I spent some time on this, and I found it was not as simple as I would have liked. Thus I have filed a ticket to track the idea I filed a ticket here I will pull that code out into its own PR for easier review as well
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note I couldn't quite figure out how to reuse that kernel code in this PR
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's unfortunate. Maybe a separate issue for that?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I thought more about this last night -- the reason I think we'll need special code other than
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I had come up with some ideas before I remembered Things get a lot trickier if we want to eliminate references to data types, tho, as the
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I think this is a good idea. I am not sure we can use the We could maybe make our own macro variant specific macro though 🤔
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -186,13 +352,11 @@ impl Array for VariantArray { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fn slice(&self, offset: usize, length: usize) -> ArrayRef { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let slice = self.inner.slice(offset, length); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let met = self.metadata_ref.slice(offset, length); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let val = self.value_ref.slice(offset, length); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let inner = self.inner.slice(offset, length); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let shredding_state = self.shredding_state.slice(offset, length); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Arc::new(Self { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can we avoid unnecessary allocations for common cases, like -
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We could definitely add a fast path for slicing the whole array. I am not quite sure what ShreddingState::All and ShreddingState::Mixed is supposed to represent
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Out of curiosity, would we actually expect a redundant DetailsFor example, pub fn slice(&self, offset: usize, length: usize) -> Self {
Self {
values: self.values.slice(offset, length),
nulls: self.nulls.as_ref().map(|n| n.slice(offset, length)),
}
}with pub fn slice(&self, offset: usize, len: usize) -> Self {
assert!(
offset.saturating_add(len) <= self.len,
"the length + offset of the sliced BooleanBuffer cannot exceed the existing length"
);
Self {
buffer: self.buffer.clone(),
offset: self.offset + offset,
len,
}
}Assuming the compiler inlines things as aggressively as it usually does, it seems like the net difference would be the bounds check and other offset arithmetic.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree I don't expect any measurable performance improvement |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| inner: slice, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| metadata_ref: met, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| value_ref: val, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| inner, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| shredding_state, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -258,7 +422,7 @@ mod test { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let err = VariantArray::try_new(Arc::new(array)); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert_eq!( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| err.unwrap_err().to_string(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "Invalid argument error: Invalid VariantArray: StructArray must contain a 'value' field" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "Invalid argument error: VariantArray has neither value nor typed_value field" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||

Uh oh!
There was an error while loading. Please reload this page.