File Coverage

blib/lib/DBIx/NoSQL/Search.pm
Criterion Covered Total %
statement 73 105 69.5
branch 19 38 50.0
condition 4 12 33.3
subroutine 14 20 70.0
pod 0 13 0.0
total 110 188 58.5


line stmt bran cond sub pod time code
1             package DBIx::NoSQL::Search;
2             our $AUTHORITY = 'cpan:YANICK';
3             $DBIx::NoSQL::Search::VERSION = '0.0021';
4 7     7   34 use strict;
  7         9  
  7         218  
5 7     7   26 use warnings;
  7         13  
  7         202  
6              
7 7     7   30 use Moose;
  7         10  
  7         39  
8 7     7   42456 use Hash::Merge::Simple qw/ merge /;
  7         3204  
  7         2751  
9              
10             has model => qw/ is ro required 1 /, handles => [qw/ store storage /];
11              
12             has [qw/ _where /] => qw/ is rw isa Maybe[HashRef] /;
13             has [qw/ _order_by /] => qw/ is rw isa Maybe[ArrayRef] /;
14             has [qw/ _limit _offset /] => qw/ is rw /;
15              
16             has cursor => qw/ is ro lazy_build 1 /;
17             sub _build_cursor {
18 7     7   16 my $self = shift;
19 7         27 $self->_cursor( 'value' );
20             }
21              
22             sub _cursor {
23 14     14   23 my $self = shift;
24 14         25 my $target = shift;
25 14         49 my ( $statement, @bind ) = $self->prepare( $target );
26 14         171 return $self->storage->cursor( $statement, \@bind );
27             }
28              
29             sub search {
30 0     0 0 0 my $self = shift;
31 0         0 return $self->where( @_ );
32             }
33              
34             sub where {
35 0     0 0 0 my $self = shift;
36 0         0 my $where = shift;
37              
38 0 0       0 if ( my $_where = $self->_where ) {
39 0         0 $where = merge $_where, $where;
40             }
41              
42 0         0 return $self->clone( _where => $where );
43             }
44              
45             sub order_by {
46 5     5 0 12 my $self = shift;
47 5         10 my $order_by = shift;
48              
49 5 100       21 $order_by = [ $order_by ] unless ref $order_by;
50              
51 5 50       138 if ( my $_order_by = $self->_order_by ) {
52 0         0 $order_by = [ @$_order_by, @$order_by ];
53             }
54              
55 5         22 return $self->clone( _order_by => $order_by );
56             }
57              
58              
59             sub clone {
60 5     5 0 9 my $self = shift;
61 5         12 my @override = @_;
62              
63 5         152 return ( ref $self )->new(
64             model => $self->model,
65             _where => $self->_where,
66             _order_by => $self->_order_by,
67             _limit => $self->_limit,
68             _offset => $self->_offset,
69             @override
70             );
71             }
72              
73 7     7   47 use DBIx::Class::SQLMaker;
  7         11  
  7         4923  
74             sub prepare {
75 16     16 0 1776 my $self = shift;
76 16         27 my $target = shift;
77              
78 16 100       45 $target = 'value' unless defined $target;
79              
80 16         21 my %options;
81 16 100       404 if ( my $order_by = $self->_order_by ) {
82 5         18 $options{ order_by } = $order_by;
83             }
84              
85 16         388 my @where_order_limit_offset = (
86             $self->_where,
87             \%options,
88             $self->_limit,
89             $self->_offset,
90             );
91              
92 16         160 my $maker = DBIx::Class::SQLMaker->new;
93              
94 16         694 my $entity_table = '__Store__';
95 16         426 my $model_name = $self->model->name;
96 16         25 my $search_table = $model_name;
97 16         27 my $search_key_column = 'key';
98              
99 16 100       58 if ( $target eq 'value' ) { $target = '__Store__.__value__' }
  9 50       18  
100 7         11 elsif ( $target eq 'count' ) { $target = 'COUNT(*)' }
101 0         0 else { die "Invalid target ($target)" }
102              
103 16         215 my ( $statement, @bind ) = $maker->select(
104             [
105             { me => $search_table },
106             [
107             { '-join-type' => 'LEFT', '__Store__' => $entity_table },
108             { "__Store__.__key__" => \"= me.$search_key_column", '__Store__.__model__' => \"= '$model_name'" },
109             #{ "__Store__.__key__" => "me.$search_key_column", '__Store__.__model__' => "'$model_name'" },
110             ]
111             ],
112             $target,
113             @where_order_limit_offset,
114             );
115              
116 16         8915 return ( $statement, @bind );
117             }
118              
119             sub all {
120 7     7 0 2509 my $self = shift;
121 7         30 my %options = @_;
122              
123 7         180 my $model = $self->model;
124 7   100     43 my $as = $options{ as } || 'object';
125              
126 7         194 my $cursor = $self->cursor;
127 7         180 my $all = $self->cursor->all;
128              
129 7 100 33     44 if ( $as eq 'object' ) { return map { $model->create_object( $_->[0] ) } @$all }
  4 50       9  
  6 50       27  
    0          
130 0         0 elsif ( $as eq 'entity' ) { return map { $model->create_entity( $_->[0] ) } @$all }
  0         0  
131             elsif ( $as eq 'data' ||
132 3         8 $as eq 'hash' ) { return map { $model->create_data( $_->[0] ) } @$all }
  5         23  
133 0         0 elsif ( $as eq 'value' ) { return @$all }
134 0         0 else { die "Invalid inflation target ($as)" }
135             }
136              
137             sub next {
138 2     2 0 11 my $self = shift;
139 2         3 my %options = @_;
140              
141 2         42 my $model = $self->model;
142 2   50     11 my $as = $options{ as } || 'object';
143              
144 2         40 my $cursor = $self->cursor;
145 2         7 my $value = $cursor->next;
146              
147             # cursor returns an arrayref, we want its first element
148 2 50       9 $value = $value->[0] if ref $value;
149              
150             # nothing found? eject
151 2 100       7 return unless $value;
152              
153 1 50 0     4 if ( $as eq 'object' ) { return $model->create_object( $value ) }
  1 0       145  
    0          
    0          
154 0         0 elsif ( $as eq 'entity' ) { return $model->create_entity( $value ) }
155             elsif ( $as eq 'data' ||
156 0         0 $as eq 'hash' ) { return $model->create_data( $value ) }
157 0         0 elsif ( $as eq 'value' ) { return $value }
158 0         0 else { die "Invalid inflation target ($as)" }
159             }
160              
161             sub offset {
162 0     0 0 0 my $self = shift;
163 0         0 my $offset = shift;
164              
165 0         0 return $self->clone( _offset => $offset );
166             }
167              
168             sub limit {
169 0     0 0 0 my $self = shift;
170 0         0 my $limit = shift;
171              
172 0         0 return $self->clone( _limit => $limit );
173             }
174              
175             sub slice {
176 0     0 0 0 my $self = shift;
177 0         0 my $from = shift;
178 0         0 my $to = shift;
179              
180 0   0     0 my $offset = $self->_offset || 0;
181              
182 0         0 $offset += $from;
183 0 0       0 my $limit = $to ? ( $to - $from + 1 ) : 1;
184              
185 0         0 return $self->clone( _offset => $offset, _limit => $limit );
186             }
187              
188             sub count {
189 7     7 0 9 my $self = shift;
190              
191 7         25 my $cursor = $self->_cursor( 'count' );
192 7 50       7388 return unless my $result = $cursor->next;
193 7         35 return $result->[0];
194             }
195              
196             sub fetch {
197 3     3 0 1776 my $self = shift;
198 3         17 return $self->all( as => 'data', @_ );
199             }
200              
201             sub get {
202 0     0 0   my $self = shift;
203 0           return $self->all( @_ );
204             }
205              
206             1;
207              
208             __END__
209              
210             =pod
211              
212             =encoding UTF-8
213              
214             =head1 NAME
215              
216             DBIx::NoSQL::Search
217              
218             =head1 VERSION
219              
220             version 0.0021
221              
222             =head1 AUTHORS
223              
224             =over 4
225              
226             =item *
227              
228             Robert Krimen <robertkrimen@gmail.com>
229              
230             =item *
231              
232             Yanick Champoux <yanick@cpan.org>
233              
234             =back
235              
236             =head1 COPYRIGHT AND LICENSE
237              
238             This software is copyright (c) 2017 by Robert Krimen.
239              
240             This is free software; you can redistribute it and/or modify it under
241             the same terms as the Perl 5 programming language system itself.
242              
243             =cut