GH-50993: [CI][Integration] Add extension-wrapped union to integration data - #51027
Conversation
…gration data Add a new integration datagen case (extension_union) with sparse- and dense-union columns wrapped in an extension type, so the cross-language integration tests exercise the extension/union interaction. This mirrors the C++ IPC coverage added in apacheGH-50623 (apache#50927).
|
|
The extension names in this case are not registered in the per-language integration binaries, so the C++ JSON reader (and others) rejected them with "Extension type not found". Flag them with ARROW:integration:allow_unregistered_extension so the extension metadata is preserved and the union storage is round-tripped by every implementation.
|
Nice addition @Alb3e3! |
| .skip_format(SKIP_FLIGHT, '.NET') | ||
| .skip_tester('Ruby'), | ||
|
|
||
| generate_extension_wrapped_union_case(), |
There was a problem hiding this comment.
so does this mean that all the other implementations correctly handle this extension wrapped union? If so, maybe that implies that whatever the problem was in #50927 is C++ specific and maybe not worth additional cross implementation coverage
There was a problem hiding this comment.
@alamb It depends how other implementations handle extension types. If they need to be registered as in Arrow C++ for wrapping to occur, then a bug could be hidden by lack of registration.
There was a problem hiding this comment.
Confirmed. After removing the bypass, there were still two C++ integration consumers missing extension-type registration: flight-test-integration-client and c_data_integration_internal.
With just those registrations reverted locally, archery integration --run-flight --run-c-data -x -k extension_union fails in Flight with Extension type 'sparse-union-extension' not found while opening generated_extension_union.json.
I pushed f215787 to register the dense/sparse union extension types in both places, and rerunning the same focused extension_union Flight + C Data command passes locally.
|
Fixed in de746b3. I removed Removing the bypass also exposed a related integration JSON reader issue: validity parsing was selected from the logical I verified the coverage is non-vacuous:
|
|
@Alb3e3 I think you also need to update the extension type registrations in the Flight integration test harness. |
|
The two failures on the previous head split cleanly:
Root cause was I pushed
CI has restarted from the new head. |
| const DataType* physical_type = data->type.get(); | ||
| if (physical_type->id() == Type::EXTENSION) { | ||
| physical_type = | ||
| checked_cast<const ExtensionType&>(*physical_type).storage_type().get(); | ||
| } | ||
|
|
There was a problem hiding this comment.
I'm just noticing that we can simply call DataType::storage_id here:
const auto physical_type_id = data->type->storage_id();and then:
if (n_buffers > 0 && !internal::may_have_validity_bitmap(physical_type_id)) {
| TestPrimitive(ExampleSmallint); | ||
| TestPrimitive(ExampleComplex128); | ||
| TestPrimitive([]() { | ||
| auto type = dense_union_extension_type(); |
There was a problem hiding this comment.
Perhaps add helper functions ExampleDenseUnionExtension and ExampleSparseUnionExtension along with ExampleUuid etc.?
| ExtensionTypeGuard ext_guard({uuid(), dict_extension_type(), | ||
| dense_union_extension_type(), | ||
| sparse_union_extension_type()}); |
There was a problem hiding this comment.
@paleolimbot @zeroshade I think similar guards will have to be added to arrow-go and nanoarrow so that the extension type wrapping happens in integration testing.
There was a problem hiding this comment.
Thank you for the heads up!
nanoarrow doesn't have a registration mechanism (more like arrow-rs...it's all just metadata). Do I still need to do anything for this?
There was a problem hiding this comment.
@paleolimbot Sorry for the misunderstanding. Then no, you don't have to do anything, I think :)
…ion example helpers - bridge.cc: replace the manual extension-storage unwrap with DataType::storage_id(), per review. - Add ExampleDenseUnionExtension/ExampleSparseUnionExtension to arrow/testing (extension_type.h + gtest_util.cc), alongside ExampleUuid et al., and use them in the bridge Extension export test instead of inline lambdas.
|
Thanks, both addressed in 3abb59a.
On the two cross-implementation notes: agreed that arrow-go and nanoarrow will need the same wrapping guard in their integration consumers for the extension-wrapped union to be exercised there, and that a registration gap could otherwise hide a bug. That is outside this C++/Python change; I have left it for @paleolimbot / @zeroshade as you flagged rather than pull it into this PR. |
|
Built and tested locally on macOS (Apple clang, bundled deps): the full |
Rationale for this change
Just as the C++ test suite gained coverage for extension-wrapped unions in #50927 (GH-50623), the cross-implementation integration tests should exercise this case so that every tested implementation handles an extension type whose storage is a union.
What changes are included in this PR?
A new archery integration datagen case,
extension_union, with two columns:sparse_union_ext: a sparse union (int32/utf8) wrapped in an extension typedense_union_ext: a dense union (int16/binary) wrapped in an extension typeExtensionFieldalready delegates its storage type/children/generation to the wrapped field, so no new datagen machinery is needed.Are these changes tested?
The generator produces valid integration JSON locally (schema carries the
ARROW:extension:*metadata on the union-typed fields, children preserved, batch sizes[0, 7]). The cross-implementation integration matrix in CI is the real test here — I've intentionally added the case with no per-implementation skips so the matrix can show which implementations still need a temporary.skip_tester(...); I'll add those (with tracking links) based on the results.Are there any user-facing changes?
No. This only adds integration-test data.
Closes #50993.