Skip to content

Commit d88a8f5

Browse files
authored
fix: Update FuzzDataGenerator to produce dictionary-encoded string arrays & fix bugs that this exposes (apache#2635)
1 parent 5f39006 commit d88a8f5

3 files changed

Lines changed: 12 additions & 25 deletions

File tree

native/core/src/execution/operators/scan.rs

Lines changed: 7 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
// specific language governing permissions and limitations
1616
// under the License.
1717

18-
use crate::execution::operators::copy_array;
18+
use crate::execution::operators::{copy_array, copy_or_unpack_array, CopyMode};
1919
use crate::{
2020
errors::CometError,
2121
execution::{
@@ -147,27 +147,13 @@ impl ScanExec {
147147
})
148148
}
149149

150-
/// Checks if the input data type `dt` is a dictionary type with primitive value type.
151-
/// If so, unpacks it and returns the primitive value type.
152-
///
153-
/// Otherwise, this returns the original data type.
154-
///
155-
/// This is necessary since DataFusion doesn't handle dictionary array with values
156-
/// being primitive type.
157-
///
158-
/// TODO: revisit this once DF has improved its dictionary type support. Ideally we shouldn't
159-
/// do this in Comet but rather let DF to handle it for us.
150+
/// Unpack all dictionary types because some DataFusion operators
151+
/// and expressions do not support dictionary types
160152
fn unpack_dictionary_type(dt: &DataType) -> DataType {
161153
if let DataType::Dictionary(_, vt) = dt {
162-
if !matches!(
163-
vt.as_ref(),
164-
DataType::Utf8 | DataType::LargeUtf8 | DataType::Binary | DataType::LargeBinary
165-
) {
166-
// return the underlying data type
167-
return vt.as_ref().clone();
168-
}
154+
// return the underlying data type
155+
return vt.as_ref().clone();
169156
}
170-
171157
dt.clone()
172158
}
173159

@@ -280,7 +266,8 @@ impl ScanExec {
280266

281267
let array = if arrow_ffi_safe {
282268
// ownership of this array has been transferred to native
283-
array
269+
// but we still need to unpack dictionary arrays
270+
copy_or_unpack_array(&array, &CopyMode::UnpackOrClone)?
284271
} else {
285272
// it is necessary to copy the array because the contents may be
286273
// overwritten on the JVM side in the future

native/core/src/execution/planner.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3120,11 +3120,8 @@ mod tests {
31203120
assert!(batch.is_ok(), "got error {}", batch.unwrap_err());
31213121
let batch = batch.unwrap();
31223122
assert_eq!(batch.num_rows(), row_count / 4);
3123-
// string/binary should still be packed with dictionary
3124-
assert!(matches!(
3125-
batch.column(0).data_type(),
3126-
DataType::Dictionary(_, _)
3127-
));
3123+
// string/binary should no longer be packed with dictionary
3124+
assert!(matches!(batch.column(0).data_type(), DataType::Utf8));
31283125
}
31293126
Poll::Ready(None) => {
31303127
break;

spark/src/main/scala/org/apache/comet/testing/FuzzDataGenerator.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,9 @@ object FuzzDataGenerator {
195195
case 2 => r.nextLong().toString
196196
case 3 => r.nextDouble().toString
197197
case 4 => RandomStringUtils.randomAlphabetic(8)
198+
case 5 =>
199+
// use a constant value to trigger dictionary encoding
200+
"dict_encode_me!"
198201
case _ => r.nextString(8)
199202
}
200203
})

0 commit comments

Comments
 (0)