@@ -2030,10 +2030,21 @@ mod tests {
20302030 }
20312031 }
20322032
2033+ fn assert_is_dict_utf8 ( arr : & ArrayRef , label : & str ) {
2034+ assert ! (
2035+ matches!( arr. data_type( ) ,
2036+ DataType :: Dictionary ( k, v)
2037+ if k. as_ref( ) == & DataType :: Int32 && v. as_ref( ) == & DataType :: Utf8 ) ,
2038+ "{label}: expected Dictionary(Int32, Utf8), got {:?}" ,
2039+ arr. data_type( )
2040+ ) ;
2041+ }
2042+
20332043 fn dict_utf8 ( ) -> DataType {
20342044 DataType :: Dictionary ( Box :: new ( DataType :: Int32 ) , Box :: new ( DataType :: Utf8 ) )
20352045 }
20362046
2047+ // Mixed key types (Int8/Int32) and value types (Utf8/LargeUtf8) in the same schema.
20372048 #[ test]
20382049 fn test_group_dict_repeated_keys_mixed_types_non_streaming ( ) {
20392050 let schema = Arc :: new ( Schema :: new ( vec ! [
@@ -2092,16 +2103,16 @@ mod tests {
20922103 assert_eq ! ( groups, vec![ 1 , 2 , 2 , 0 ] ) ;
20932104
20942105 let out = gv. emit ( EmitTo :: All ) . unwrap ( ) ;
2095- assert_eq ! ( out[ 0 ] . len( ) , 3 ) ;
20962106 assert_dict_str ( & out[ 0 ] , & [ Some ( "a" ) , Some ( "b" ) , Some ( "c" ) ] ) ;
20972107 let s = cast ( out[ 1 ] . as_ref ( ) , & DataType :: LargeUtf8 ) . unwrap ( ) ;
20982108 let s = s. as_any ( ) . downcast_ref :: < LargeStringArray > ( ) . unwrap ( ) ;
2099- let got: Vec < Option < & str > > = ( 0 ..s. len ( ) )
2100- . map ( |i| if s . is_null ( i) { None } else { Some ( s. value ( i) ) } )
2109+ let got: Vec < _ > = ( 0 ..s. len ( ) )
2110+ . map ( |i| s . is_valid ( i) . then ( || s. value ( i) ) )
21012111 . collect ( ) ;
21022112 assert_eq ! ( got, vec![ Some ( "x" ) , Some ( "y" ) , Some ( "z" ) ] ) ;
21032113 }
21042114
2115+ // Dict cols mixed with a primitive col; both non-streaming and streaming paths.
21052116 #[ test]
21062117 fn test_group_dict_with_primitive_non_streaming ( ) {
21072118 let dt = dict_utf8 ( ) ;
@@ -2110,39 +2121,45 @@ mod tests {
21102121 Field :: new( "b" , dt. clone( ) , true ) ,
21112122 Field :: new( "c" , DataType :: Int64 , true ) ,
21122123 ] ) ) ;
2113- let mut gv = GroupValuesColumn :: < false > :: try_new ( Arc :: clone ( & schema) ) . unwrap ( ) ;
2114- let mut groups = vec ! [ ] ;
2115-
2116- gv. intern (
2117- & [
2118- dict_col ( & [ Some ( "a" ) , Some ( "b" ) , Some ( "a" ) ] ) ,
2119- dict_col ( & [ Some ( "x" ) , Some ( "y" ) , Some ( "x" ) ] ) ,
2120- Arc :: new ( Int64Array :: from ( vec ! [ Some ( 1 ) , Some ( 2 ) , Some ( 1 ) ] ) ) ,
2121- ] ,
2122- & mut groups,
2123- )
2124- . unwrap ( ) ;
2125- assert_eq ! ( groups, vec![ 0 , 1 , 0 ] ) ;
21262124
2127- gv. intern (
2128- & [
2129- dict_col ( & [ Some ( "a" ) , Some ( "c" ) ] ) ,
2130- dict_col ( & [ Some ( "x" ) , Some ( "z" ) ] ) ,
2131- Arc :: new ( Int64Array :: from ( vec ! [ Some ( 1 ) , Some ( 3 ) ] ) ) ,
2132- ] ,
2133- & mut groups,
2134- )
2135- . unwrap ( ) ;
2136- assert_eq ! ( groups, vec![ 0 , 2 ] ) ;
2125+ let run = |mut gv : Box < dyn GroupValues > | {
2126+ let mut groups = vec ! [ ] ;
2127+ gv. intern (
2128+ & [
2129+ dict_col ( & [ Some ( "a" ) , Some ( "b" ) , Some ( "a" ) ] ) ,
2130+ dict_col ( & [ Some ( "x" ) , Some ( "y" ) , Some ( "x" ) ] ) ,
2131+ Arc :: new ( Int64Array :: from ( vec ! [ 1i64 , 2 , 1 ] ) ) ,
2132+ ] ,
2133+ & mut groups,
2134+ )
2135+ . unwrap ( ) ;
2136+ assert_eq ! ( groups, vec![ 0 , 1 , 0 ] ) ;
2137+ gv. intern (
2138+ & [
2139+ dict_col ( & [ Some ( "a" ) , Some ( "c" ) ] ) ,
2140+ dict_col ( & [ Some ( "x" ) , Some ( "z" ) ] ) ,
2141+ Arc :: new ( Int64Array :: from ( vec ! [ 1i64 , 3 ] ) ) ,
2142+ ] ,
2143+ & mut groups,
2144+ )
2145+ . unwrap ( ) ;
2146+ assert_eq ! ( groups, vec![ 0 , 2 ] ) ;
2147+ let out = gv. emit ( EmitTo :: All ) . unwrap ( ) ;
2148+ assert_dict_str ( & out[ 0 ] , & [ Some ( "a" ) , Some ( "b" ) , Some ( "c" ) ] ) ;
2149+ assert_dict_str ( & out[ 1 ] , & [ Some ( "x" ) , Some ( "y" ) , Some ( "z" ) ] ) ;
2150+ let c = out[ 2 ] . as_any ( ) . downcast_ref :: < Int64Array > ( ) . unwrap ( ) ;
2151+ assert_eq ! ( c. values( ) , & [ 1 , 2 , 3 ] ) ;
2152+ } ;
21372153
2138- let out = gv. emit ( EmitTo :: All ) . unwrap ( ) ;
2139- assert_dict_str ( & out[ 0 ] , & [ Some ( "a" ) , Some ( "b" ) , Some ( "c" ) ] ) ;
2140- assert_dict_str ( & out[ 1 ] , & [ Some ( "x" ) , Some ( "y" ) , Some ( "z" ) ] ) ;
2141- let c = out[ 2 ] . as_any ( ) . downcast_ref :: < Int64Array > ( ) . unwrap ( ) ;
2142- assert_eq ! ( c. values( ) , & [ 1 , 2 , 3 ] ) ;
2154+ run ( Box :: new (
2155+ GroupValuesColumn :: < false > :: try_new ( Arc :: clone ( & schema) ) . unwrap ( ) ,
2156+ ) ) ;
2157+ run ( Box :: new (
2158+ GroupValuesColumn :: < true > :: try_new ( Arc :: clone ( & schema) ) . unwrap ( ) ,
2159+ ) ) ;
21432160 }
21442161
2145- // 3 dict cols with null values — nulls in different columns must form distinct groups
2162+ // Nulls in different columns must form distinct groups.
21462163 #[ test]
21472164 fn test_group_three_dict_cols_with_nulls_non_streaming ( ) {
21482165 let dt = dict_utf8 ( ) ;
@@ -2171,124 +2188,37 @@ mod tests {
21712188 assert_dict_str ( & out[ 2 ] , & [ Some ( "p" ) , Some ( "p" ) , Some ( "q" ) ] ) ;
21722189 }
21732190
2174- // Emitted dict columns must carry the exact schema DataType, not the inner value type .
2191+ // Emitted columns must carry the exact schema DataType via both build and take_n paths .
21752192 #[ test]
21762193 fn test_emit_dict_output_exact_type ( ) {
21772194 let dt = dict_utf8 ( ) ;
2178- let schema = Arc :: new ( Schema :: new ( vec ! [
2179- Field :: new( "a" , dt. clone( ) , true ) ,
2180- Field :: new( "b" , dt. clone( ) , true ) ,
2181- ] ) ) ;
2195+ let schema = Arc :: new ( Schema :: new ( vec ! [ Field :: new( "a" , dt. clone( ) , true ) ] ) ) ;
2196+
2197+ // non-streaming: build path
21822198 let mut gv = GroupValuesColumn :: < false > :: try_new ( Arc :: clone ( & schema) ) . unwrap ( ) ;
21832199 let mut groups = vec ! [ ] ;
2184-
2185- gv. intern (
2186- & [
2187- dict_col ( & [ Some ( "x" ) , None , Some ( "y" ) ] ) ,
2188- dict_col ( & [ None , Some ( "p" ) , Some ( "p" ) ] ) ,
2189- ] ,
2190- & mut groups,
2191- )
2192- . unwrap ( ) ;
2200+ gv. intern ( & [ dict_col ( & [ Some ( "x" ) , None , Some ( "y" ) ] ) ] , & mut groups)
2201+ . unwrap ( ) ;
21932202 assert_eq ! ( groups, vec![ 0 , 1 , 2 ] ) ;
2194-
21952203 let out = gv. emit ( EmitTo :: All ) . unwrap ( ) ;
2196- for ( i, arr) in out. iter ( ) . enumerate ( ) {
2197- assert ! (
2198- matches!(
2199- arr. data_type( ) ,
2200- DataType :: Dictionary ( k, v)
2201- if k. as_ref( ) == & DataType :: Int32 && v. as_ref( ) == & DataType :: Utf8
2202- ) ,
2203- "col {i}: expected Dictionary(Int32, Utf8), got {:?}" ,
2204- arr. data_type( )
2205- ) ;
2206- }
2204+ assert_is_dict_utf8 ( & out[ 0 ] , "build" ) ;
22072205 assert_dict_str ( & out[ 0 ] , & [ Some ( "x" ) , None , Some ( "y" ) ] ) ;
2208- assert_dict_str ( & out[ 1 ] , & [ None , Some ( "p" ) , Some ( "p" ) ] ) ;
2209- }
2210-
2211- // Streaming variant: same exact-type guarantee via take_n path
2212- #[ test]
2213- fn test_emit_dict_output_exact_type_streaming ( ) {
2214- let dt = dict_utf8 ( ) ;
2215- let schema = Arc :: new ( Schema :: new ( vec ! [ Field :: new( "a" , dt. clone( ) , true ) ] ) ) ;
2216- let mut gv = GroupValuesColumn :: < true > :: try_new ( Arc :: clone ( & schema) ) . unwrap ( ) ;
2217- let mut groups = vec ! [ ] ;
22182206
2219- gv. intern (
2207+ // streaming: take_n then build
2208+ let mut gv2 = GroupValuesColumn :: < true > :: try_new ( Arc :: clone ( & schema) ) . unwrap ( ) ;
2209+ gv2. intern (
22202210 & [ dict_col ( & [ Some ( "alpha" ) , Some ( "beta" ) , None ] ) ] ,
22212211 & mut groups,
22222212 )
22232213 . unwrap ( ) ;
2224- assert_eq ! ( groups, vec![ 0 , 1 , 2 ] ) ;
2225-
2226- let out = gv. emit ( EmitTo :: First ( 2 ) ) . unwrap ( ) ;
2227- assert ! (
2228- matches!(
2229- out[ 0 ] . data_type( ) ,
2230- DataType :: Dictionary ( k, v)
2231- if k. as_ref( ) == & DataType :: Int32 && v. as_ref( ) == & DataType :: Utf8
2232- ) ,
2233- "take_n output: expected Dictionary(Int32, Utf8), got {:?}" ,
2234- out[ 0 ] . data_type( )
2235- ) ;
2236- assert_dict_str ( & out[ 0 ] , & [ Some ( "alpha" ) , Some ( "beta" ) ] ) ;
2237-
2238- let remaining = gv. emit ( EmitTo :: All ) . unwrap ( ) ;
2239- assert ! (
2240- matches!(
2241- remaining[ 0 ] . data_type( ) ,
2242- DataType :: Dictionary ( k, v)
2243- if k. as_ref( ) == & DataType :: Int32 && v. as_ref( ) == & DataType :: Utf8
2244- ) ,
2245- "build output: expected Dictionary(Int32, Utf8), got {:?}" ,
2246- remaining[ 0 ] . data_type( )
2247- ) ;
2214+ let taken = gv2. emit ( EmitTo :: First ( 2 ) ) . unwrap ( ) ;
2215+ assert_is_dict_utf8 ( & taken[ 0 ] , "take_n" ) ;
2216+ assert_dict_str ( & taken[ 0 ] , & [ Some ( "alpha" ) , Some ( "beta" ) ] ) ;
2217+ let remaining = gv2. emit ( EmitTo :: All ) . unwrap ( ) ;
2218+ assert_is_dict_utf8 ( & remaining[ 0 ] , "build after take_n" ) ;
22482219 assert_dict_str ( & remaining[ 0 ] , & [ None ] ) ;
22492220 }
22502221
2251- // streaming=true covers the scalarized_intern code path
2252- #[ test]
2253- fn test_group_dict_with_primitive_streaming ( ) {
2254- let dt = dict_utf8 ( ) ;
2255- let schema = Arc :: new ( Schema :: new ( vec ! [
2256- Field :: new( "a" , dt. clone( ) , true ) ,
2257- Field :: new( "b" , dt. clone( ) , true ) ,
2258- Field :: new( "c" , DataType :: Int64 , true ) ,
2259- ] ) ) ;
2260- let mut gv = GroupValuesColumn :: < true > :: try_new ( Arc :: clone ( & schema) ) . unwrap ( ) ;
2261- let mut groups = vec ! [ ] ;
2262-
2263- gv. intern (
2264- & [
2265- dict_col ( & [ Some ( "a" ) , Some ( "b" ) , Some ( "a" ) ] ) ,
2266- dict_col ( & [ Some ( "x" ) , Some ( "y" ) , Some ( "x" ) ] ) ,
2267- Arc :: new ( Int64Array :: from ( vec ! [ Some ( 10 ) , Some ( 20 ) , Some ( 10 ) ] ) ) ,
2268- ] ,
2269- & mut groups,
2270- )
2271- . unwrap ( ) ;
2272- assert_eq ! ( groups, vec![ 0 , 1 , 0 ] ) ;
2273-
2274- gv. intern (
2275- & [
2276- dict_col ( & [ Some ( "a" ) , Some ( "c" ) ] ) ,
2277- dict_col ( & [ Some ( "x" ) , Some ( "z" ) ] ) ,
2278- Arc :: new ( Int64Array :: from ( vec ! [ Some ( 10 ) , Some ( 30 ) ] ) ) ,
2279- ] ,
2280- & mut groups,
2281- )
2282- . unwrap ( ) ;
2283- assert_eq ! ( groups, vec![ 0 , 2 ] ) ;
2284-
2285- let out = gv. emit ( EmitTo :: All ) . unwrap ( ) ;
2286- assert_dict_str ( & out[ 0 ] , & [ Some ( "a" ) , Some ( "b" ) , Some ( "c" ) ] ) ;
2287- assert_dict_str ( & out[ 1 ] , & [ Some ( "x" ) , Some ( "y" ) , Some ( "z" ) ] ) ;
2288- let c = out[ 2 ] . as_any ( ) . downcast_ref :: < Int64Array > ( ) . unwrap ( ) ;
2289- assert_eq ! ( c. values( ) , & [ 10 , 20 , 30 ] ) ;
2290- }
2291-
22922222 fn insert_non_inline_group_index_view (
22932223 group_values : & mut GroupValuesColumn < false > ,
22942224 hash_key : u64 ,
0 commit comments