@@ -19,7 +19,7 @@ import Arrow from '../Arrow';
19
19
20
20
const { predicate, Table } = Arrow ;
21
21
22
- const { col } = predicate ;
22
+ const { col, lit } = predicate ;
23
23
24
24
const F32 = 0 , I32 = 1 , DICT = 2 ;
25
25
const test_data = [
@@ -299,25 +299,51 @@ describe(`Table`, () => {
299
299
expect ( row . toArray ( ) ) . toEqual ( values [ i ++ ] ) ;
300
300
}
301
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 ++ ] ) ;
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
+ } ) ;
307
309
} ) ;
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
+ } )
309
318
test ( `count() returns the correct length` , ( ) => {
310
319
expect ( table . count ( ) ) . toEqual ( values . length ) ;
311
320
} ) ;
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
+ } ) ;
312
326
const filter_tests = [
313
327
{
314
328
name : `filter on f32 >= 0` ,
315
329
filtered : table . filter ( col ( 'f32' ) . gteq ( 0 ) ) ,
316
330
expected : values . filter ( ( row ) => row [ F32 ] >= 0 )
317
331
} , {
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` ,
319
337
filtered : table . filter ( col ( 'i32' ) . lteq ( 0 ) ) ,
320
338
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 )
321
347
} , {
322
348
name : `filter method combines predicates (f32 >= 0 && i32 <= 0)` ,
323
349
filtered : table . filter ( col ( 'i32' ) . lteq ( 0 ) ) . filter ( col ( 'f32' ) . gteq ( 0 ) ) ,
@@ -326,20 +352,44 @@ describe(`Table`, () => {
326
352
name : `filter on dictionary == 'a'` ,
327
353
filtered : table . filter ( col ( 'dictionary' ) . eq ( 'a' ) ) ,
328
354
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 ] )
329
367
}
330
368
] ;
331
369
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 , ( ) => {
335
372
test ( `count() returns the correct length` , ( ) => {
336
373
expect ( filtered . count ( ) ) . toEqual ( expected . length ) ;
337
374
} ) ;
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
+ }
343
393
} ) ;
344
394
} ) ;
345
395
} ) ;
@@ -367,6 +417,9 @@ describe(`Table`, () => {
367
417
expect ( ( ) => { table . countBy ( 'i32' ) ; } ) . toThrow ( ) ;
368
418
expect ( ( ) => { table . filter ( col ( 'dict' ) . eq ( 'a' ) ) . countBy ( 'i32' ) ; } ) . toThrow ( ) ;
369
419
} ) ;
420
+ test ( `countBy on non-existent column throws error` , ( ) => {
421
+ expect ( ( ) => { table . countBy ( 'FAKE' ) ; } ) . toThrow ( ) ;
422
+ } ) ;
370
423
test ( `table.select() basic tests` , ( ) => {
371
424
let selected = table . select ( 'f32' , 'dictionary' ) ;
372
425
expect ( selected . schema . fields . length ) . toEqual ( 2 ) ;
@@ -391,6 +444,28 @@ describe(`Table`, () => {
391
444
} ) ] . join ( '\n' ) + '\n' ;
392
445
expect ( selected . toString ( ) ) . toEqual ( expected ) ;
393
446
} ) ;
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
+ } ) ;
394
469
} ) ;
395
470
}
396
471
} ) ;
0 commit comments