@@ -21,13 +21,10 @@ const { predicate, Table } = Arrow;
21
21
22
22
const { col } = predicate ;
23
23
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 ( {
31
28
'schema' : {
32
29
'fields' : [
33
30
{
@@ -115,79 +112,19 @@ describe(`Table`, () => {
115
112
}
116
113
]
117
114
} ]
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 ( {
191
128
'schema' : {
192
129
'fields' : [
193
130
{
@@ -319,11 +256,8 @@ describe(`Table`, () => {
319
256
}
320
257
]
321
258
} ]
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 : [
327
261
[ Math . fround ( - 0.3 ) , - 1 , 'a' ] ,
328
262
[ Math . fround ( - 0.2 ) , 1 , 'b' ] ,
329
263
[ Math . fround ( - 0.1 ) , - 1 , 'c' ] ,
@@ -333,63 +267,134 @@ describe(`Table`, () => {
333
267
[ Math . fround ( 0.3 ) , - 1 , 'a' ] ,
334
268
[ Math . fround ( 0.2 ) , 1 , 'b' ] ,
335
269
[ 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
+ } ) ;
349
346
}
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 ) ;
356
357
} ) ;
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 ) ;
377
365
} ) ;
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 ( ) ;
382
369
} ) ;
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 ) ;
389
393
} ) ;
390
394
} ) ;
391
- test ( `countBy on non dictionary column throws error` , ( ) => {
392
- expect ( ( ) => { table . countBy ( 'i32' ) ; } ) . toThrow ( ) ;
393
- } ) ;
394
- } ) ;
395
+ }
395
396
} ) ;
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