diff --git a/lib/Rethinkdb/Query.pm b/lib/Rethinkdb/Query.pm index b347675..6316a54 100644 --- a/lib/Rethinkdb/Query.pm +++ b/lib/Rethinkdb/Query.pm @@ -414,17 +414,21 @@ sub sample { sub group { my $self = shift; my $args = [@_]; + my $optargs = {}; - my $reductor; - if ( ref $args->[ $#{$args} ] ) { - $reductor = pop @{$args}; - $args = [ $args, $reductor ]; + if ( ref $args->[ $#{$args} ] eq 'HASH' ) { + $optargs = pop @{$args}; + } + + if( ref $args->[0] && ref $args->[0] ne 'CODE' ) { + $args = Rethinkdb::Util->_wrap_func($args->[0]); } my $q = Rethinkdb::Query->new( _parent => $self, _type => $self->_termType->group, - args => $args + args => $args, + optargs => $optargs ); return $q; @@ -469,7 +473,7 @@ sub count { sub sum { my $self = shift; - my $args = {@_}; + my $args = [@_]; my $q = Rethinkdb::Query->new( _parent => $self, @@ -495,7 +499,7 @@ sub avg { sub min { my $self = shift; - my $args = {@_}; + my $args = [@_]; my $q = Rethinkdb::Query->new( _parent => $self, @@ -508,7 +512,7 @@ sub min { sub max { my $self = shift; - my $args = {@_}; + my $args = [@_]; my $q = Rethinkdb::Query->new( _parent => $self, diff --git a/t/aggregation.t b/t/aggregation.t index 593b34a..1b5da27 100644 --- a/t/aggregation.t +++ b/t/aggregation.t @@ -161,6 +161,49 @@ r->table('dc')->insert( ] )->run; +# group +$res = r->table('marvel')->group('age')->avg('strength')->run; + +is $res->type, 1, 'Correct response type'; +is_deeply $res->response, + { + '1035' => '2035', + '35' => '543.166666666667', + '135' => '1035', + '20' => '200', + }, + 'Correct response'; + +# group by more than one field (we have to use `group_format=>'raw'`) +$res = r->table('marvel')->group( 'age', 'active' ) + ->run( { group_format => 'raw' } ); + +is_deeply $res->response->{data}->[0][0], [ 20, 0 ]; +is $res->response->{data}->[0][1][0]->{superhero}, 'Spider-Man'; + +# group using a function +$res = r->table('marvel')->group( + sub { + my $row = shift; + return $row->pluck( 'age', 'active' ); + } +)->run( { group_format => 'raw' } ); + +is_deeply $res->response->{data}->[0][0], { age => 20, active => 0 }; +is $res->response->{data}->[0][1][0]->{superhero}, 'Spider-Man'; + +# group `multi=true` +# r.table('games2').group(r.row['matches'].keys(), multi=True).run() +$res = r->table('marvel') + ->group( r->row->bracket('dc_buddies'), { multi => r->true } )->run; + +is $#{ $res->response->{Batman} }, 3, 'Correct `multi=true` response'; + +# ungroup +$res = r->table('marvel')->group('age')->avg('strength')->ungroup->run; + +is_deeply [ sort keys %{ $res->response->[0] } ], [ 'group', 'reduction' ]; + # reduce $res = r->table('marvel')->map( r->row->bracket('age') )->reduce( sub ($$) { @@ -199,6 +242,84 @@ $res = r->table('marvel')->count( is $res->type, 1, 'Correct response type'; is $res->response, '4', 'Correct number of documents'; +# sum +$res = r->expr( [ 3, 5, 7 ] )->sum->run($conn); + +is $res->response, 15, 'Correct response'; + +# sum - document attributes +$res = r->table('marvel')->sum('age')->run; + +is $res->response, 1400, 'Correct response'; + +# sum - documents based on function +$res = r->table('marvel')->sum( + sub { + my $row = shift; + return $row->bracket('strength')->mul( $row->bracket('active') ); + } +)->run; + +is $res->response, 6132, 'Correct response'; + +# avg +$res = r->expr( [ 3, 5, 7 ] )->avg->run($conn); + +is $res->response, 5, 'Correct response'; + +# avg - document attributes +$res = r->table('marvel')->avg('age')->run; + +is substr( $res->response, 0, 7 ), '155.555', 'Correct response'; + +# avg - documents based on function +$res = r->table('marvel')->avg( + sub { + my $row = shift; + return $row->bracket('strength')->mul( $row->bracket('active') ); + } +)->run; + +is substr( $res->response, 0, 7 ), '681.333', 'Correct response'; + +# min +$res = r->expr( [ 3, 5, 7 ] )->min->run($conn); + +is $res->response, 3, 'Correct response'; + +# min - document attributes +$res = r->table('marvel')->min('age')->run; +is $res->response->{age}, 20, 'Correct response'; + +# min - documents based on function +$res = r->table('marvel')->min( + sub { + my $row = shift; + return $row->bracket('strength')->mul( $row->bracket('active') ); + } +)->run; + +is $res->response->{age}, 20, 'Correct response'; + +# max +$res = r->expr( [ 3, 5, 7 ] )->max->run($conn); + +is $res->response, 7, 'Correct response'; + +# max - document attributes +$res = r->table('marvel')->max('age')->run; +is $res->response->{age}, 1035, 'Correct response'; + +# max - documents based on function +$res = r->table('marvel')->max( + sub { + my $row = shift; + return $row->bracket('strength')->mul( $row->bracket('active') ); + } +)->run; + +is $res->response->{age}, 1035, 'Correct response'; + # distinct (on table) $res = r->table('marvel')->distinct->run; @@ -211,19 +332,6 @@ $res = r->expr( [ 1, 1, 1, 1, 1, 2, 3 ] )->distinct->run($conn); is $res->type, 1, 'Correct response type'; is scalar @{ $res->response }, 3, 'Correct number of documents'; -# group_by -$res = r->table('marvel')->group('age')->avg('strength')->run; - -is $res->type, 1, 'Correct response type'; -is_deeply $res->response, - { - '1035' => '2035', - '35' => '543.166666666667', - '135' => '1035', - '20' => '200', - }, - 'Correct response'; - # contains $res = r->table('marvel')->get('Iron Man')->bracket('dc_buddies') ->contains('Superman')->run; @@ -231,6 +339,17 @@ $res = r->table('marvel')->get('Iron Man')->bracket('dc_buddies') is $res->type, 1, 'Correct response type'; is $res->response, r->true, 'Correct response value'; +$res = r->table('marvel')->filter( + sub { + my $hero = shift; + return r->expr( [ 'Smash', 'Size' ] ) + ->contains( $hero->bracket('superpower') ); + } +)->bracket('superhero')->run; + +is_deeply sort $res->response, [ 'Ant-Man', 'Hulk' ], + 'Correct filter & contains response'; + # clean up r->db('test')->drop->run; diff --git a/t/control.t b/t/control.t index f999306..26ab809 100644 --- a/t/control.t +++ b/t/control.t @@ -22,6 +22,7 @@ r->table('marvel')->insert( battles => 3, villainDefeated => 'Mandarin', outfits => 12, + gadget => 'Shoulder-mounted rocket launcher' }, { user_id => 8, @@ -40,7 +41,8 @@ r->table('marvel')->insert( age => 20, victories => 24, battles => 3, - villainDefeated => 'Green Goblin' + villainDefeated => 'Green Goblin', + gadget => 'Web-slinger' } ] )->run; @@ -126,6 +128,13 @@ is $res->type, 2, 'Correct response type'; is_deeply [ sort { $a <=> $b } @{ $res->response } ], [ '0', '2', '13' ], 'Correct response'; +$res = r->table('marvel')->map(r->row->bracket('gadget')->default)->run; + +is $res->type, 2, 'Correct response type'; +is_deeply [ sort @{ $res->response } ], [ undef, 'Shoulder-mounted rocket launcher', 'Web-slinger' ], + 'Correct response'; + + # expr $res = r->expr( { 'a' => 'b' } )->merge( { 'b' => [ 1, 2, 3 ] } )->run($conn); diff --git a/t/document.t b/t/document.t index 49b6717..8dec517 100644 --- a/t/document.t +++ b/t/document.t @@ -226,6 +226,54 @@ $res = r->table('marvel')->get('Iron Man')->bracket('equipment') is $res->type, 1, 'Correct response type'; is_deeply $res->response, ['oldHelm']; +# get_field +$res = r->table('marvel')->get('Iron Man')->get_field('reactorState')->run; + +is $res->type, 1, 'Correct response type'; +is $res->response, 'medium', 'Correct response'; + +$res = r->table('marvel')->get_field('superpower')->run; + +is $res->type, 2, 'Correct response type'; +is_deeply [sort @{$res->response}], + [ + 'Adamantium', 'Bio-lasers', 'Bow-n-arrow', 'God-like powers', + 'Size', 'Smash', 'Spidy Sense', 'Super Strength', + ], + 'Correct response'; + +# bracket +$res = r->table('marvel')->get('Iron Man')->bracket('reactorState')->run; + +is $res->type, 1, 'Correct response type'; +is $res->response, 'medium', 'Correct response'; + +$res = r->table('marvel')->bracket('superpower')->run; + +is $res->type, 2, 'Correct response type'; +is_deeply [sort @{$res->response}], + [ + 'Adamantium', 'Bio-lasers', 'Bow-n-arrow', 'God-like powers', + 'Size', 'Smash', 'Spidy Sense', 'Super Strength', + ], + 'Correct response'; + +# attr - depercated +$res = r->table('marvel')->get('Iron Man')->attr('reactorState')->run; + +is $res->type, 1, 'Correct response type'; +is $res->response, 'medium', 'Correct response'; + +$res = r->table('marvel')->attr('superpower')->run; + +is $res->type, 2, 'Correct response type'; +is_deeply [sort @{$res->response}], + [ + 'Adamantium', 'Bio-lasers', 'Bow-n-arrow', 'God-like powers', + 'Size', 'Smash', 'Spidy Sense', 'Super Strength', + ], + 'Correct response'; + # Plucks out one or more attributes from either an object or a sequence of # objects (projection). $res = r->table('marvel')->get('Iron Man') diff --git a/t/string.t b/t/string.t index f96810d..7a26196 100644 --- a/t/string.t +++ b/t/string.t @@ -23,4 +23,31 @@ isa_ok $res, 'Rethinkdb::Response'; is $res->type, 1, 'Correct status code'; is $res->response, undef, 'Correct number of updates'; +# split +$res = r->expr('foo bar bax')->split->run($conn); + +isa_ok $res, 'Rethinkdb::Response'; +is $res->type, 1, 'Correct status code'; +is_deeply $res->response, ['foo', 'bar', 'bax'], 'Correct split response'; + +$res = r->expr('id:0,foo:bar,stuff:good')->split(',')->run($conn); + +isa_ok $res, 'Rethinkdb::Response'; +is $res->type, 1, 'Correct status code'; +is_deeply $res->response, ['id:0', 'foo:bar', 'stuff:good'], 'Correct split response'; + +# upcase +$res = r->expr('Sentence about LaTeX.')->upcase->run($conn); + +isa_ok $res, 'Rethinkdb::Response'; +is $res->type, 1, 'Correct status code'; +is $res->response, 'SENTENCE ABOUT LATEX.', 'Correct split response'; + +# downcase +$res = r->expr('Sentence about LaTeX.')->downcase->run($conn); + +isa_ok $res, 'Rethinkdb::Response'; +is $res->type, 1, 'Correct status code'; +is $res->response, 'sentence about latex.', 'Correct split response'; + done_testing();