@@ -21,13 +21,10 @@ const { predicate, Table } = Arrow;
2121
2222const { col } = predicate ;
2323
24- describe ( `Table` , ( ) => {
25- test ( `can create an empty table` , ( ) => {
26- expect ( Table . empty ( ) . length ) . toEqual ( 0 ) ;
27- } ) ;
28-
29- describe ( `single record batch` , ( ) => {
30- const table = Table . from ( {
24+ const F32 = 0 , I32 = 1 , DICT = 2 ;
25+ const test_data = [
26+ { name : `single record batch` ,
27+ table : Table . from ( {
3128 'schema' : {
3229 'fields' : [
3330 {
@@ -115,79 +112,19 @@ describe(`Table`, () => {
115112 }
116113 ]
117114 } ]
118- } ) ;
119-
120- // Wrap floating point values in a Float32Array and take them back out to
121- // make sure that equality checks will pass
122- const values = [
123- [ Math . fround ( - 0.3 ) , - 1 , 'a' ] ,
124- [ Math . fround ( - 0.2 ) , 1 , 'b' ] ,
125- [ Math . fround ( - 0.1 ) , - 1 , 'c' ] ,
126- [ Math . fround ( 0 ) , 1 , 'a' ] ,
127- [ Math . fround ( 0.1 ) , - 1 , 'b' ] ,
128- [ Math . fround ( 0.2 ) , 1 , 'c' ] ,
129- [ Math . fround ( 0.3 ) , - 1 , 'a' ]
130- ] ;
131- test ( `has the correct length` , ( ) => {
132- expect ( table . length ) . toEqual ( values . length ) ;
133- } ) ;
134- test ( `gets expected values` , ( ) => {
135- for ( let i = - 1 ; ++ i < values . length ; ) {
136- expect ( table . get ( i ) . toArray ( ) ) . toEqual ( values [ i ] ) ;
137- }
138- } ) ;
139- test ( `iterates expected values` , ( ) => {
140- let i = 0 ;
141- for ( let row of table ) {
142- expect ( row . toArray ( ) ) . toEqual ( values [ i ++ ] ) ;
143- }
144- } ) ;
145- test ( `scans expected values` , ( ) => {
146- let expected_idx = 0 ;
147- table . scan ( ( idx , batch ) => {
148- const columns = batch . schema . fields . map ( ( _ , i ) => batch . getChildAt ( i ) ! ) ;
149- expect ( columns . map ( ( c ) => c . get ( idx ) ) ) . toEqual ( values [ expected_idx ++ ] ) ;
150- } ) ;
151- } ) ;
152- test ( `count() returns the correct length` , ( ) => {
153- expect ( table . count ( ) ) . toEqual ( values . length ) ;
154- } ) ;
155- test ( `filter on f32 >= 0 returns the correct length` , ( ) => {
156- expect ( table . filter ( col ( 'f32' ) . gteq ( 0 ) ) . count ( ) ) . toEqual ( 4 ) ;
157- } ) ;
158- test ( `filter on i32 <= 0 returns the correct length` , ( ) => {
159- expect ( table . filter ( col ( 'i32' ) . lteq ( 0 ) ) . count ( ) ) . toEqual ( 4 ) ;
160- } ) ;
161- test ( `filter on dictionary == 'a' returns the correct length` , ( ) => {
162- expect ( table . filter ( col ( 'dictionary' ) . eq ( 'a' ) ) . count ( ) ) . toEqual ( 3 ) ;
163- } ) ;
164- test ( `countBy on dictionary returns the correct counts` , ( ) => {
165- // Make sure countBy works both with and without the Col wrapper
166- // class
167- expect ( table . countBy ( col ( 'dictionary' ) ) . toJSON ( ) ) . toEqual ( {
168- 'a' : 3 ,
169- 'b' : 2 ,
170- 'c' : 2 ,
171- } ) ;
172- expect ( table . countBy ( 'dictionary' ) . toJSON ( ) ) . toEqual ( {
173- 'a' : 3 ,
174- 'b' : 2 ,
175- 'c' : 2 ,
176- } ) ;
177- } ) ;
178- test ( `countBy on dictionary with filter returns the correct counts` , ( ) => {
179- expect ( table . filter ( col ( 'i32' ) . eq ( 1 ) ) . countBy ( 'dictionary' ) . toJSON ( ) ) . toEqual ( {
180- 'a' : 1 ,
181- 'b' : 1 ,
182- 'c' : 1 ,
183- } ) ;
184- } ) ;
185- test ( `countBy on non dictionary column throws error` , ( ) => {
186- expect ( ( ) => { table . countBy ( 'i32' ) ; } ) . toThrow ( ) ;
187- } ) ;
188- } ) ;
189- describe ( `multiple record batches` , ( ) => {
190- const table = Table . from ( {
115+ } ) ,
116+ // Use Math.fround to coerce to float32
117+ values : [
118+ [ Math . fround ( - 0.3 ) , - 1 , 'a' ] ,
119+ [ Math . fround ( - 0.2 ) , 1 , 'b' ] ,
120+ [ Math . fround ( - 0.1 ) , - 1 , 'c' ] ,
121+ [ Math . fround ( 0 ) , 1 , 'a' ] ,
122+ [ Math . fround ( 0.1 ) , - 1 , 'b' ] ,
123+ [ Math . fround ( 0.2 ) , 1 , 'c' ] ,
124+ [ Math . fround ( 0.3 ) , - 1 , 'a' ]
125+ ] } ,
126+ { name : `multiple record batches` ,
127+ table : Table . from ( {
191128 'schema' : {
192129 'fields' : [
193130 {
@@ -319,11 +256,8 @@ describe(`Table`, () => {
319256 }
320257 ]
321258 } ]
322- } ) ;
323-
324- // Wrap floating point values in a Float32Array and take them back out to
325- // make sure that equality checks will pass
326- const values = [
259+ } ) ,
260+ values : [
327261 [ Math . fround ( - 0.3 ) , - 1 , 'a' ] ,
328262 [ Math . fround ( - 0.2 ) , 1 , 'b' ] ,
329263 [ Math . fround ( - 0.1 ) , - 1 , 'c' ] ,
@@ -333,63 +267,134 @@ describe(`Table`, () => {
333267 [ Math . fround ( 0.3 ) , - 1 , 'a' ] ,
334268 [ Math . fround ( 0.2 ) , 1 , 'b' ] ,
335269 [ Math . fround ( 0.1 ) , - 1 , 'c' ] ,
336- ] ;
337- test ( `has the correct length` , ( ) => {
338- expect ( table . length ) . toEqual ( values . length ) ;
339- } ) ;
340- test ( `gets expected values` , ( ) => {
341- for ( let i = - 1 ; ++ i < values . length ; ) {
342- expect ( table . get ( i ) . toArray ( ) ) . toEqual ( values [ i ] ) ;
343- }
344- } ) ;
345- test ( `iterates expected values` , ( ) => {
346- let i = 0 ;
347- for ( let row of table ) {
348- expect ( row . toArray ( ) ) . toEqual ( values [ i ++ ] ) ;
270+ ] }
271+ ]
272+
273+ describe ( `Table` , ( ) => {
274+ test ( `can create an empty table` , ( ) => {
275+ expect ( Table . empty ( ) . length ) . toEqual ( 0 ) ;
276+ } ) ;
277+ test ( `Table.from([]) creates an empty table` , ( ) => {
278+ expect ( Table . from ( [ ] ) . length ) . toEqual ( 0 ) ;
279+ } ) ;
280+ test ( `Table.from() creates an empty table` , ( ) => {
281+ expect ( Table . from ( ) . length ) . toEqual ( 0 ) ;
282+ } ) ;
283+ for ( let datum of test_data ) {
284+ describe ( datum . name , ( ) => {
285+ const table = datum . table ;
286+ const values = datum . values ;
287+
288+ test ( `has the correct length` , ( ) => {
289+ expect ( table . length ) . toEqual ( values . length ) ;
290+ } ) ;
291+ test ( `gets expected values` , ( ) => {
292+ for ( let i = - 1 ; ++ i < values . length ; ) {
293+ expect ( table . get ( i ) . toArray ( ) ) . toEqual ( values [ i ] ) ;
294+ }
295+ } ) ;
296+ test ( `iterates expected values` , ( ) => {
297+ let i = 0 ;
298+ for ( let row of table ) {
299+ expect ( row . toArray ( ) ) . toEqual ( values [ i ++ ] ) ;
300+ }
301+ } ) ;
302+ test ( `scans expected values` , ( ) => {
303+ let expected_idx = 0 ;
304+ table . scan ( ( idx , batch ) => {
305+ const columns = batch . schema . fields . map ( ( _ , i ) => batch . getChildAt ( i ) ! ) ;
306+ expect ( columns . map ( ( c ) => c . get ( idx ) ) ) . toEqual ( values [ expected_idx ++ ] ) ;
307+ } ) ;
308+ } ) ;
309+ test ( `count() returns the correct length` , ( ) => {
310+ expect ( table . count ( ) ) . toEqual ( values . length ) ;
311+ } ) ;
312+ const filter_tests = [
313+ {
314+ name : `filter on f32 >= 0` ,
315+ filtered : table . filter ( col ( 'f32' ) . gteq ( 0 ) ) ,
316+ expected : values . filter ( ( row ) => row [ F32 ] >= 0 )
317+ } , {
318+ name : `filter on i32 <= 0 returns the correct length` ,
319+ filtered : table . filter ( col ( 'i32' ) . lteq ( 0 ) ) ,
320+ expected : values . filter ( ( row ) => row [ I32 ] <= 0 )
321+ } , {
322+ name : `filter method combines predicates (f32 >= 0 && i32 <= 0)` ,
323+ filtered : table . filter ( col ( 'i32' ) . lteq ( 0 ) ) . filter ( col ( 'f32' ) . gteq ( 0 ) ) ,
324+ expected : values . filter ( ( row ) => row [ I32 ] <= 0 && row [ F32 ] >= 0 )
325+ } , {
326+ name : `filter on dictionary == 'a'` ,
327+ filtered : table . filter ( col ( 'dictionary' ) . eq ( 'a' ) ) ,
328+ expected : values . filter ( ( row ) => row [ DICT ] === 'a' )
329+ }
330+ ]
331+ for ( let this_test of filter_tests ) {
332+ describe ( `filter on f32 >= 0` , ( ) => {
333+ const filtered = this_test . filtered ;
334+ const expected = this_test . expected ;
335+ test ( `count() returns the correct length` , ( ) => {
336+ expect ( filtered . count ( ) ) . toEqual ( expected . length ) ;
337+ } ) ;
338+ test ( `scans expected values` , ( ) => {
339+ let expected_idx = 0 ;
340+ filtered . scan ( ( idx , batch ) => {
341+ const columns = batch . schema . fields . map ( ( _ , i ) => batch . getChildAt ( i ) ! ) ;
342+ expect ( columns . map ( ( c ) => c . get ( idx ) ) ) . toEqual ( expected [ expected_idx ++ ] ) ;
343+ } ) ;
344+ } )
345+ } ) ;
349346 }
350- } ) ;
351- test ( `scans expected values` , ( ) => {
352- let expected_idx = 0 ;
353- table . scan ( ( idx , batch ) => {
354- const columns = batch . schema . fields . map ( ( _ , i ) => batch . getChildAt ( i ) ! ) ;
355- expect ( columns . map ( ( c ) => c . get ( idx ) ) ) . toEqual ( values [ expected_idx ++ ] ) ;
347+ test ( `countBy on dictionary returns the correct counts` , ( ) => {
348+ // Make sure countBy works both with and without the Col wrapper
349+ // class
350+ let expected : { [ key : string ] : number } = { 'a' : 0 , 'b' : 0 , 'c' : 0 } ;
351+ for ( let row of values ) {
352+ expected [ row [ DICT ] ] += 1 ;
353+ }
354+
355+ expect ( table . countBy ( col ( 'dictionary' ) ) . toJSON ( ) ) . toEqual ( expected ) ;
356+ expect ( table . countBy ( 'dictionary' ) . toJSON ( ) ) . toEqual ( expected ) ;
356357 } ) ;
357- } ) ;
358- test ( `count() returns the correct length` , ( ) => {
359- expect ( table . count ( ) ) . toEqual ( values . length ) ;
360- } ) ;
361- test ( `filter on f32 >= 0 returns the correct length` , ( ) => {
362- expect ( table . filter ( col ( 'f32' ) . gteq ( 0 ) ) . count ( ) ) . toEqual ( 6 ) ;
363- } ) ;
364- test ( `filter on i32 <= 0 returns the correct length` , ( ) => {
365- expect ( table . filter ( col ( 'i32' ) . lteq ( 0 ) ) . count ( ) ) . toEqual ( 5 ) ;
366- } ) ;
367- test ( `filter on dictionary == 'a' returns the correct length` , ( ) => {
368- expect ( table . filter ( col ( 'dictionary' ) . eq ( 'a' ) ) . count ( ) ) . toEqual ( 3 ) ;
369- } ) ;
370- test ( `countBy on dictionary returns the correct counts` , ( ) => {
371- // Make sure countBy works both with and without the Col wrapper
372- // class
373- expect ( table . countBy ( col ( 'dictionary' ) ) . toJSON ( ) ) . toEqual ( {
374- 'a' : 3 ,
375- 'b' : 3 ,
376- 'c' : 3 ,
358+ test ( `countBy on dictionary with filter returns the correct counts` , ( ) => {
359+ let expected : { [ key : string ] : number } = { 'a' : 0 , 'b' : 0 , 'c' : 0 } ;
360+ for ( let row of values ) {
361+ if ( row [ I32 ] === 1 ) { expected [ row [ DICT ] ] += 1 ; }
362+ }
363+
364+ expect ( table . filter ( col ( 'i32' ) . eq ( 1 ) ) . countBy ( 'dictionary' ) . toJSON ( ) ) . toEqual ( expected ) ;
377365 } ) ;
378- expect ( table . countBy ( 'dictionary' ) . toJSON ( ) ) . toEqual ( {
379- 'a' : 3 ,
380- 'b' : 3 ,
381- 'c' : 3 ,
366+ test ( `countBy on non dictionary column throws error` , ( ) => {
367+ expect ( ( ) => { table . countBy ( 'i32' ) ; } ) . toThrow ( ) ;
368+ expect ( ( ) => { table . filter ( col ( 'dict' ) . eq ( 'a' ) ) . countBy ( 'i32' ) ; } ) . toThrow ( ) ;
382369 } ) ;
383- } ) ;
384- test ( `countBy on dictionary with filter returns the correct counts` , ( ) => {
385- expect ( table . filter ( col ( 'i32' ) . eq ( 1 ) ) . countBy ( col ( 'dictionary' ) ) . toJSON ( ) ) . toEqual ( {
386- 'a' : 1 ,
387- 'b' : 2 ,
388- 'c' : 1 ,
370+ test ( `table.select() basic tests` , ( ) => {
371+ let selected = table . select ( 'f32' , 'dictionary' ) ;
372+ expect ( selected . schema . fields . length ) . toEqual ( 2 ) ;
373+ expect ( selected . schema . fields [ 0 ] ) . toEqual ( table . schema . fields [ 0 ] ) ;
374+ expect ( selected . schema . fields [ 1 ] ) . toEqual ( table . schema . fields [ 2 ] ) ;
375+
376+ expect ( selected . length ) . toEqual ( values . length ) ;
377+ let idx = 0 , expected_row ;
378+ for ( let row of selected ) {
379+ expected_row = values [ idx ++ ] ;
380+ expect ( row . get ( 0 ) ) . toEqual ( expected_row [ F32 ] ) ;
381+ expect ( row . get ( 1 ) ) . toEqual ( expected_row [ DICT ] ) ;
382+ }
383+ } ) ;
384+ test ( `table.toString()` , ( ) => {
385+ let selected = table . select ( 'i32' , 'dictionary' ) ;
386+ let headers = [ `"row_id"` , `"i32: Int32"` , `"dictionary: Dictionary<Utf8, Int8>"` ]
387+ let expected = [ headers . join ( ' | ' ) , ...values . map ( ( row , idx ) => {
388+ return [ `${ idx } ` , `${ row [ I32 ] } ` , `"${ row [ DICT ] } "` ] . map ( ( str , col ) => {
389+ return leftPad ( str , ' ' , headers [ col ] . length ) ;
390+ } ) . join ( ' | ' ) ;
391+ } ) ] . join ( '\n' ) + '\n' ;
392+ expect ( selected . toString ( ) ) . toEqual ( expected ) ;
389393 } ) ;
390394 } ) ;
391- test ( `countBy on non dictionary column throws error` , ( ) => {
392- expect ( ( ) => { table . countBy ( 'i32' ) ; } ) . toThrow ( ) ;
393- } ) ;
394- } ) ;
395+ }
395396} ) ;
397+
398+ function leftPad ( str : string , fill : string , n : number ) {
399+ return ( new Array ( n + 1 ) . join ( fill ) + str ) . slice ( - 1 * n ) ;
400+ }
0 commit comments