1313// See the License for the specific language governing permissions and
1414// limitations under the License.
1515
16+ using System ;
1617using System . Linq ;
1718using Apache . Arrow . Types ;
1819using Xunit ;
@@ -24,7 +25,7 @@ public class UnionArrayTests
2425 [ Theory ]
2526 [ InlineData ( UnionMode . Sparse ) ]
2627 [ InlineData ( UnionMode . Dense ) ]
27- public void UnionArray_IsNull ( UnionMode mode )
28+ public void UnionArrayIsNull ( UnionMode mode )
2829 {
2930 var ( array , expectedNull ) = BuildUnionArray ( mode , 100 ) ;
3031
@@ -38,40 +39,100 @@ public void UnionArray_IsNull(UnionMode mode)
3839 [ Theory ]
3940 [ InlineData ( UnionMode . Sparse ) ]
4041 [ InlineData ( UnionMode . Dense ) ]
41- public void UnionArray_Slice ( UnionMode mode )
42+ public void UnionArraySlice ( UnionMode mode )
4243 {
4344 var ( array , expectedNull ) = BuildUnionArray ( mode , 10 ) ;
4445
4546 for ( var offset = 0 ; offset < array . Length ; ++ offset )
4647 {
4748 for ( var length = 0 ; length < array . Length - offset ; ++ length )
4849 {
49- var slicedArray = ArrowArrayFactory . Slice ( array , offset , length ) ;
50+ var slicedArray = ( UnionArray ) ArrowArrayFactory . Slice ( array , offset , length ) ;
5051
5152 var nullCount = 0 ;
5253 for ( var i = 0 ; i < slicedArray . Length ; ++ i )
5354 {
54- // TODO: Shouldn't need to add offset in IsNull/IsValid calls,
55- // see https://github.com/apache/arrow/issues/41140
56- Assert . Equal ( expectedNull [ offset + i ] , slicedArray . IsNull ( offset + i ) ) ;
57- Assert . Equal ( ! expectedNull [ offset + i ] , slicedArray . IsValid ( offset + i ) ) ;
55+ Assert . Equal ( expectedNull [ offset + i ] , slicedArray . IsNull ( i ) ) ;
56+ Assert . Equal ( ! expectedNull [ offset + i ] , slicedArray . IsValid ( i ) ) ;
5857 nullCount += expectedNull [ offset + i ] ? 1 : 0 ;
58+
59+ CompareValue ( array , offset + i , slicedArray , i ) ;
5960 }
6061
61- Assert . True ( nullCount == slicedArray . NullCount , $ "offset = { offset } , length = { length } ") ;
6262 Assert . Equal ( nullCount , slicedArray . NullCount ) ;
6363 }
6464 }
6565 }
6666
67- private static ( UnionArray array , bool [ ] isNull ) BuildUnionArray ( UnionMode mode , int length )
67+ [ Theory ]
68+ [ InlineData ( UnionMode . Sparse ) ]
69+ [ InlineData ( UnionMode . Dense ) ]
70+ public void UnionArrayConstructedWithOffset ( UnionMode mode )
71+ {
72+ const int length = 10 ;
73+ var ( array , expectedNull ) = BuildUnionArray ( mode , length ) ;
74+
75+ for ( var offset = 0 ; offset < array . Length ; ++ offset )
76+ {
77+ var ( slicedArray , _) = BuildUnionArray ( mode , length , offset ) ;
78+
79+ var nullCount = 0 ;
80+ for ( var i = 0 ; i < slicedArray . Length ; ++ i )
81+ {
82+ Assert . Equal ( expectedNull [ offset + i ] , slicedArray . IsNull ( i ) ) ;
83+ Assert . Equal ( ! expectedNull [ offset + i ] , slicedArray . IsValid ( i ) ) ;
84+ nullCount += expectedNull [ offset + i ] ? 1 : 0 ;
85+
86+ CompareValue ( array , offset + i , slicedArray , i ) ;
87+ }
88+
89+ Assert . Equal ( nullCount , slicedArray . NullCount ) ;
90+ }
91+ }
92+
93+ private static void CompareValue ( UnionArray originalArray , int originalIndex , UnionArray slicedArray , int sliceIndex )
94+ {
95+ var typeId = originalArray . TypeIds [ originalIndex ] ;
96+ var sliceTypeId = slicedArray . TypeIds [ sliceIndex ] ;
97+ Assert . Equal ( typeId , sliceTypeId ) ;
98+
99+ switch ( typeId )
100+ {
101+ case 0 :
102+ CompareFieldValue < int , Int32Array > ( typeId , originalArray , originalIndex , slicedArray , sliceIndex ) ;
103+ break ;
104+ case 1 :
105+ CompareFieldValue < float , FloatArray > ( typeId , originalArray , originalIndex , slicedArray , sliceIndex ) ;
106+ break ;
107+ default :
108+ throw new Exception ( $ "Unexpected type id { typeId } ") ;
109+ }
110+ }
111+
112+ private static void CompareFieldValue < T , TArray > ( byte typeId , UnionArray originalArray , int originalIndex , UnionArray slicedArray , int sliceIndex )
113+ where T : struct
114+ where TArray : PrimitiveArray < T >
115+ {
116+ if ( originalArray is DenseUnionArray denseOriginalArray )
117+ {
118+ Assert . IsType < DenseUnionArray > ( slicedArray ) ;
119+
120+ originalIndex = denseOriginalArray . ValueOffsets [ originalIndex ] ;
121+ sliceIndex = ( ( DenseUnionArray ) slicedArray ) . ValueOffsets [ sliceIndex ] ;
122+ }
123+ var originalValue = ( ( TArray ) originalArray . Fields [ typeId ] ) . GetValue ( originalIndex ) ;
124+ var sliceValue = ( ( TArray ) slicedArray . Fields [ typeId ] ) . GetValue ( sliceIndex ) ;
125+ Assert . Equal ( originalValue , sliceValue ) ;
126+ }
127+
128+ private static ( UnionArray array , bool [ ] isNull ) BuildUnionArray ( UnionMode mode , int length , int offset = 0 )
68129 {
69130 var fields = new Field [ ]
70131 {
71132 new Field ( "field0" , new Int32Type ( ) , true ) ,
72133 new Field ( "field1" , new FloatType ( ) , true ) ,
73134 } ;
74- var typeIds = fields . Select ( f => ( int ) f . DataType . TypeId ) . ToArray ( ) ;
135+ var typeIds = new [ ] { 0 , 1 } ;
75136 var type = new UnionType ( fields , typeIds , mode ) ;
76137
77138 var nullCount = 0 ;
@@ -85,7 +146,7 @@ private static (UnionArray array, bool[] isNull) BuildUnionArray(UnionMode mode,
85146 {
86147 var isNull = i % 3 == 0 ;
87148 expectedNull [ i ] = isNull ;
88- nullCount += isNull ? 1 : 0 ;
149+ nullCount += ( isNull && i >= offset ) ? 1 : 0 ;
89150
90151 if ( i % 2 == 0 )
91152 {
@@ -140,8 +201,8 @@ private static (UnionArray array, bool[] isNull) BuildUnionArray(UnionMode mode,
140201 } ;
141202
142203 UnionArray array = mode == UnionMode . Dense
143- ? new DenseUnionArray ( type , length , children , typeIdsBuffer , valuesOffsetBuffer , nullCount )
144- : new SparseUnionArray ( type , length , children , typeIdsBuffer , nullCount ) ;
204+ ? new DenseUnionArray ( type , length - offset , children , typeIdsBuffer , valuesOffsetBuffer , nullCount , offset )
205+ : new SparseUnionArray ( type , length - offset , children , typeIdsBuffer , nullCount , offset ) ;
145206
146207 return ( array , expectedNull ) ;
147208 }
0 commit comments