@@ -19,7 +19,7 @@ import Arrow from '../Arrow';
1919
2020const { predicate, Table } = Arrow ;
2121
22- const { col } = predicate ;
22+ const { col, lit } = predicate ;
2323
2424const F32 = 0 , I32 = 1 , DICT = 2 ;
2525const test_data = [
@@ -299,25 +299,51 @@ describe(`Table`, () => {
299299 expect ( row . toArray ( ) ) . toEqual ( values [ i ++ ] ) ;
300300 }
301301 } ) ;
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 ++ ] ) ;
302+ describe ( `scan()` , ( ) => {
303+ test ( `yields all values` , ( ) => {
304+ let expected_idx = 0 ;
305+ table . scan ( ( idx , batch ) => {
306+ const columns = batch . schema . fields . map ( ( _ , i ) => batch . getChildAt ( i ) ! ) ;
307+ expect ( columns . map ( ( c ) => c . get ( idx ) ) ) . toEqual ( values [ expected_idx ++ ] ) ;
308+ } ) ;
307309 } ) ;
308- } ) ;
310+ test ( `calls bind function with every batch` , ( ) => {
311+ let bind = jest . fn ( ) ;
312+ table . scan ( ( ) => { } , bind ) ;
313+ for ( let batch of table . batches ) {
314+ expect ( bind ) . toHaveBeenCalledWith ( batch ) ;
315+ }
316+ } )
317+ } )
309318 test ( `count() returns the correct length` , ( ) => {
310319 expect ( table . count ( ) ) . toEqual ( values . length ) ;
311320 } ) ;
321+ test ( `getColumnIndex` , ( ) => {
322+ expect ( table . getColumnIndex ( 'i32' ) ) . toEqual ( I32 ) ;
323+ expect ( table . getColumnIndex ( 'f32' ) ) . toEqual ( F32 ) ;
324+ expect ( table . getColumnIndex ( 'dictionary' ) ) . toEqual ( DICT ) ;
325+ } ) ;
312326 const filter_tests = [
313327 {
314328 name : `filter on f32 >= 0` ,
315329 filtered : table . filter ( col ( 'f32' ) . gteq ( 0 ) ) ,
316330 expected : values . filter ( ( row ) => row [ F32 ] >= 0 )
317331 } , {
318- name : `filter on i32 <= 0 returns the correct length` ,
332+ name : `filter on 0 <= f32` ,
333+ filtered : table . filter ( lit ( 0 ) . lteq ( col ( 'f32' ) ) ) ,
334+ expected : values . filter ( ( row ) => 0 <= row [ F32 ] )
335+ } , {
336+ name : `filter on i32 <= 0` ,
319337 filtered : table . filter ( col ( 'i32' ) . lteq ( 0 ) ) ,
320338 expected : values . filter ( ( row ) => row [ I32 ] <= 0 )
339+ } , {
340+ name : `filter on 0 >= i32` ,
341+ filtered : table . filter ( lit ( 0 ) . gteq ( col ( 'i32' ) ) ) ,
342+ expected : values . filter ( ( row ) => 0 >= row [ I32 ] )
343+ } , {
344+ name : `filter on f32 <= -.25 || f3 >= .25` ,
345+ filtered : table . filter ( col ( 'f32' ) . lteq ( - .25 ) . or ( col ( 'f32' ) . gteq ( .25 ) ) ) ,
346+ expected : values . filter ( ( row ) => row [ F32 ] <= - .25 || row [ F32 ] >= .25 )
321347 } , {
322348 name : `filter method combines predicates (f32 >= 0 && i32 <= 0)` ,
323349 filtered : table . filter ( col ( 'i32' ) . lteq ( 0 ) ) . filter ( col ( 'f32' ) . gteq ( 0 ) ) ,
@@ -326,20 +352,44 @@ describe(`Table`, () => {
326352 name : `filter on dictionary == 'a'` ,
327353 filtered : table . filter ( col ( 'dictionary' ) . eq ( 'a' ) ) ,
328354 expected : values . filter ( ( row ) => row [ DICT ] === 'a' )
355+ } , {
356+ name : `filter on 'a' == dictionary (commutativity)` ,
357+ filtered : table . filter ( lit ( 'a' ) . eq ( col ( 'dictionary' ) ) ) ,
358+ expected : values . filter ( ( row ) => row [ DICT ] === 'a' )
359+ } , {
360+ name : `filter on f32 >= i32` ,
361+ filtered : table . filter ( col ( 'f32' ) . gteq ( col ( 'i32' ) ) ) ,
362+ expected : values . filter ( ( row ) => row [ F32 ] >= row [ I32 ] )
363+ } , {
364+ name : `filter on f32 <= i32` ,
365+ filtered : table . filter ( col ( 'f32' ) . lteq ( col ( 'i32' ) ) ) ,
366+ expected : values . filter ( ( row ) => row [ F32 ] <= row [ I32 ] )
329367 }
330368 ] ;
331369 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 ;
370+ const { name, filtered, expected } = this_test ;
371+ describe ( name , ( ) => {
335372 test ( `count() returns the correct length` , ( ) => {
336373 expect ( filtered . count ( ) ) . toEqual ( expected . length ) ;
337374 } ) ;
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 ++ ] ) ;
375+ describe ( `scan()` , ( ) => {
376+ test ( `iterates over expected values` , ( ) => {
377+ let expected_idx = 0 ;
378+ filtered . scan ( ( idx , batch ) => {
379+ const columns = batch . schema . fields . map ( ( _ , i ) => batch . getChildAt ( i ) ! ) ;
380+ expect ( columns . map ( ( c ) => c . get ( idx ) ) ) . toEqual ( expected [ expected_idx ++ ] ) ;
381+ } ) ;
382+ } ) ;
383+ test ( `calls bind function on every batch` , ( ) => {
384+ // Techincally, we only need to call bind on
385+ // batches with data that match the predicate, so
386+ // this test may fail in the future if we change
387+ // that - and that's ok!
388+ let bind = jest . fn ( ) ;
389+ filtered . scan ( ( ) => { } , bind ) ;
390+ for ( let batch of table . batches ) {
391+ expect ( bind ) . toHaveBeenCalledWith ( batch ) ;
392+ }
343393 } ) ;
344394 } ) ;
345395 } ) ;
@@ -367,6 +417,9 @@ describe(`Table`, () => {
367417 expect ( ( ) => { table . countBy ( 'i32' ) ; } ) . toThrow ( ) ;
368418 expect ( ( ) => { table . filter ( col ( 'dict' ) . eq ( 'a' ) ) . countBy ( 'i32' ) ; } ) . toThrow ( ) ;
369419 } ) ;
420+ test ( `countBy on non-existent column throws error` , ( ) => {
421+ expect ( ( ) => { table . countBy ( 'FAKE' ) ; } ) . toThrow ( ) ;
422+ } ) ;
370423 test ( `table.select() basic tests` , ( ) => {
371424 let selected = table . select ( 'f32' , 'dictionary' ) ;
372425 expect ( selected . schema . fields . length ) . toEqual ( 2 ) ;
@@ -391,6 +444,28 @@ describe(`Table`, () => {
391444 } ) ] . join ( '\n' ) + '\n' ;
392445 expect ( selected . toString ( ) ) . toEqual ( expected ) ;
393446 } ) ;
447+ test ( `table.filter(..).count() on always false predicates returns 0` , ( ) => {
448+ expect ( table . filter ( col ( 'i32' ) . gteq ( 100 ) ) . count ( ) ) . toEqual ( 0 ) ;
449+ expect ( table . filter ( col ( 'dictionary' ) . eq ( 'z' ) ) . count ( ) ) . toEqual ( 0 ) ;
450+ } ) ;
451+ describe ( `lit-lit comparison` , ( ) => {
452+ test ( `always-false count() returns 0` , ( ) => {
453+ expect ( table . filter ( lit ( 'abc' ) . eq ( 'def' ) ) . count ( ) ) . toEqual ( 0 ) ;
454+ expect ( table . filter ( lit ( 0 ) . gteq ( 1 ) ) . count ( ) ) . toEqual ( 0 ) ;
455+ } ) ;
456+ test ( `always-true count() returns length` , ( ) => {
457+ expect ( table . filter ( lit ( 'abc' ) . eq ( 'abc' ) ) . count ( ) ) . toEqual ( table . length ) ;
458+ expect ( table . filter ( lit ( - 100 ) . lteq ( 0 ) ) . count ( ) ) . toEqual ( table . length ) ;
459+ } ) ;
460+ } ) ;
461+ describe ( `col-col comparison` , ( ) => {
462+ test ( `always-false count() returns 0` , ( ) => {
463+ expect ( table . filter ( col ( 'dictionary' ) . eq ( col ( 'i32' ) ) ) . count ( ) ) . toEqual ( 0 ) ;
464+ } ) ;
465+ test ( `always-true count() returns length` , ( ) => {
466+ expect ( table . filter ( col ( 'dictionary' ) . eq ( col ( 'dictionary' ) ) ) . count ( ) ) . toEqual ( table . length ) ;
467+ } ) ;
468+ } ) ;
394469 } ) ;
395470 }
396471} ) ;
0 commit comments