@@ -180,54 +180,47 @@ NUdf::TUnboxedValue ExtractUnboxedValue(const std::shared_ptr<arrow::Array>& arr
180180NUdf::TUnboxedValue ExtractUnboxedValue (const std::shared_ptr<arrow::Array>& array, ui64 row,
181181 const NMiniKQL::TOptionalType* optionalType, const NMiniKQL::THolderFactory& holderFactory)
182182{
183- auto innerOptionalType = SkipTaggedType (optionalType->GetItemType ());
184- if (NeedWrapByExternalOptional (innerOptionalType)) {
185- YQL_ENSURE (array->type_id () == arrow::Type::STRUCT, " Unexpected array type" );
186-
187- auto innerArray = array;
188- auto innerType = static_cast <const NMiniKQL::TType*>(optionalType);
189- int depth = 0 ;
190-
191- while (innerArray->type_id () == arrow::Type::STRUCT) {
192- auto structArray = static_pointer_cast<arrow::StructArray>(innerArray);
193- YQL_ENSURE (structArray->num_fields () == 1 , " Unexpected count of fields" );
194-
195- if (structArray->IsNull (row)) {
196- NUdf::TUnboxedValue value;
197- for (int i = 0 ; i < depth; ++i) {
198- value = value.MakeOptional ();
199- }
200- return value;
201- }
183+ auto innerType = SkipTaggedType (optionalType->GetItemType ());
184+ ui32 depth = 1 ;
202185
203- innerType = SkipTaggedType ( static_cast < const NMiniKQL::TOptionalType*>( innerType)-> GetItemType ());
204- innerArray = structArray-> field ( 0 );
205- ++depth;
206- }
186+ while ( innerType-> IsOptional ()) {
187+ innerType = SkipTaggedType ( static_cast < const NMiniKQL::TOptionalType*>(innerType)-> GetItemType () );
188+ ++depth;
189+ }
207190
208- if (innerType->IsOptional ()) { // depth + 1 == count of structs for types with validity bitmaps
209- innerType = SkipTaggedType (static_cast <const NMiniKQL::TOptionalType*>(innerType)->GetItemType ());
210- ++depth;
211- }
191+ // For types without native validity bitmap (e.g., Variant, Null) we need to wrap them in an additional struct layer
192+ // Furthermore, other singular types (e.g., Void, EmptyList, EmptyDict) also need to wrap (from YQL-15332)
193+ // Thus, the depth == 2 for Optional<Variant<T, F, ...>> type
194+ if (NeedWrapByExternalOptional (innerType)) {
195+ ++depth;
196+ }
212197
213- auto wrap = NeedWrapByExternalOptional (innerType) ;
214- auto isNull = innerArray-> IsNull (row) ;
198+ auto innerArray = array ;
199+ NUdf::TUnboxedValue value ;
215200
216- NUdf::TUnboxedValue value;
217- if (wrap || !isNull) {
218- value = NFormats::ExtractUnboxedValue (innerArray, row, innerType, holderFactory );
219- }
201+ for (ui32 i = 1 ; i < depth; ++i) {
202+ YQL_ENSURE (innerArray-> type_id () == arrow::Type::STRUCT, " Unexpected array type " );
203+ auto structArray = static_pointer_cast<arrow::StructArray> (innerArray);
204+ YQL_ENSURE (structArray-> num_fields () == 1 , " Unexpected count of fields " );
220205
221- if (wrap || isNull) {
222- --depth;
206+ if (structArray->IsNull (row)) {
207+ for (ui32 j = 1 ; j < i; ++j) {
208+ value = value.MakeOptional ();
209+ }
210+ return value;
223211 }
224212
225- for (int i = 0 ; i < depth; ++i) {
226- value = value.MakeOptional ();
227- }
228- return value;
213+ innerArray = structArray->field (0 );
214+ }
215+
216+ if (!innerArray->IsNull (row)) {
217+ value = NFormats::ExtractUnboxedValue (innerArray, row, innerType, holderFactory);
229218 }
230- return NFormats::ExtractUnboxedValue (array, row, innerOptionalType, holderFactory).Release ().MakeOptional ();
219+
220+ for (ui32 i = 1 ; i < depth; ++i) {
221+ value = value.MakeOptional ();
222+ }
223+ return value;
231224}
232225
233226NUdf::TUnboxedValue ExtractUnboxedValue (const std::shared_ptr<arrow::Array>& array, ui64 row,
0 commit comments