File Coverage

blib/lib/Net/Async/CassandraCQL/Query.pm
Criterion Covered Total %
statement 50 53 94.3
branch 10 14 71.4
condition 2 3 66.6
subroutine 16 18 88.8
pod 9 10 90.0
total 87 98 88.7


line stmt bran cond sub pod time code
1             # You may distribute under the terms of either the GNU General Public License
2             # or the Artistic License (the same terms as Perl itself)
3             #
4             # (C) Paul Evans, 2013-2014 -- leonerd@leonerd.org.uk
5              
6             package Net::Async::CassandraCQL::Query;
7              
8 13     13   77 use strict;
  13         29  
  13         497  
9 13     13   97 use warnings;
  13         27  
  13         636  
10              
11             our $VERSION = '0.11';
12              
13 13     13   70 use Carp;
  13         24  
  13         784  
14              
15 13     13   10739 use Devel::GlobalDestruction qw( in_global_destruction );
  13         30984  
  13         101  
16              
17             =head1 NAME
18              
19             C - a Cassandra CQL prepared query
20              
21             =head1 DESCRIPTION
22              
23             Prepared query objects are returned by the C of
24             L to represent a prepared query in the server. They
25             can be executed multiple times, if required, by passing the values of the
26             placeholders to the C method.
27              
28             For backward compatibility, as this object class is no longer a subclass of
29             L, the following methods will be directed
30             to the C instance.
31              
32             columns column_name column_shortname column_type find_column
33             encode_data decode_data
34              
35             However, most of them are available more directly as the C methods.
36             Code should not rely on these temporary redirects remaining in a future
37             version.
38              
39             =cut
40              
41             sub new
42             {
43 4     4 0 1557 my $class = shift;
44 4         26 my %args = @_;
45              
46 4         84 my $self = bless {
47             cassandra => $args{cassandra},
48             cql => $args{cql},
49             id => $args{id},
50             params_meta => $args{params_meta},
51             result_meta => $args{result_meta},
52             }, $class;
53              
54 4         19 return $self;
55             }
56              
57             sub DESTROY
58             {
59 6 50   6   6620 return if in_global_destruction;
60 6         49 my $self = shift;
61 6 100       232 my $cass = $self->{cassandra} or return;
62              
63 3         9 $cass->_expire_query( $self->cql );
64             }
65              
66             =head1 METHODS
67              
68             =cut
69              
70             foreach my $method (qw( columns column_name column_shortname column_type find_column
71             encode_data decode_data )) {
72 13     13   2545 no strict 'refs';
  13         30  
  13         6352  
73             *$method = sub {
74 0     0   0 my $self = shift;
75 0         0 $self->params_meta->$method( @_ )
76             };
77             }
78              
79             =head2 $id = $query->id
80              
81             Returns the query ID.
82              
83             =cut
84              
85             sub id
86             {
87 13     13 1 703 my $self = shift;
88 13         117 return $self->{id};
89             }
90              
91             =head2 $cql = $query->cql
92              
93             Returns the original query string used to prepare the query.
94              
95             =cut
96              
97             sub cql
98             {
99 9     9 1 16 my $self = shift;
100 9         43 return $self->{cql};
101             }
102              
103             =head2 $meta = $query->params_meta
104              
105             Returns a L instance with the metadata
106             about the bind parameters.
107              
108             =cut
109              
110             sub params_meta
111             {
112 7     7 1 13 my $self = shift;
113 7         31 return $self->{params_meta};
114             }
115              
116             =head2 $n_params = $query->params
117              
118             =head2 $name = $query->param_name( $idx )
119              
120             =head2 ( $keyspace, $table, $column ) = $query->param_name( $idx )
121              
122             =head2 $name = $query->param_shortname( $idx )
123              
124             =head2 $type = $query->param_type( $idx )
125              
126             Redirections to the appropriately named method on the C object.
127              
128             =cut
129              
130 2     2 1 90 sub params { shift->params_meta->columns }
131 1     1 1 496 sub param_name { shift->params_meta->column_name( @_ ) }
132 0     0 1 0 sub param_shortname { shift->params_meta->column_shortname( @_ ) }
133 1     1 1 535 sub param_type { shift->params_meta->column_type( @_ ) }
134              
135             =head2 $meta = $query->result_meta
136              
137             Returns a L instance with the metadata
138             about the query result. This will only be defined on connections with a
139             C of 2 or above.
140              
141             =cut
142              
143             sub result_meta
144             {
145 6     6 1 1023 my $self = shift;
146 6         33 return $self->{result_meta};
147             }
148              
149             =head2 $query->execute( $data, $consistency ) ==> ( $type, $result )
150              
151             Executes the query on the Cassandra connection object that created it,
152             returning a future yielding the result the same way as the C or
153             C methods.
154              
155             The contents of the C<$data> reference will be encoded according to the types
156             given in the underlying column metadata. C<$data> may be given as a positional
157             ARRAY reference, or a named HASH reference where the keys give column names.
158              
159             =cut
160              
161             sub execute
162             {
163 3     3 1 2067 my $self = shift;
164 3         7 my ( $data, $consistency ) = @_;
165              
166 3         8 my $params_meta = $self->params_meta;
167              
168 3         6 my @data;
169 3 100       14 if( ref $data eq "ARRAY" ) {
    50          
170 2         6 @data = @$data;
171             }
172             elsif( ref $data eq "HASH" ) {
173 1         6 @data = ( undef ) x $params_meta->columns;
174 1         10 foreach my $name ( keys %$data ) {
175 1         5 my $idx = $params_meta->find_column( $name );
176 1 50       9 defined $idx or croak "Unknown bind column name '$name'";
177 1 50       18 defined $data[$idx] and croak "Cannot bind column ".$params_meta->column_name($idx)." twice";
178 1         4 $data[$idx] = $data->{$name};
179             }
180             }
181              
182 3         16 my @bytes = $params_meta->encode_data( @data );
183              
184             return $self->{cassandra}->execute(
185             $self, \@bytes, $consistency,
186             skip_metadata => defined $self->result_meta,
187             )->on_done( sub {
188 3     3   289 my ( $type, $result ) = @_;
189              
190 3 100 66     18 $result->set_metadata( $self->result_meta ) if $result and !$result->has_metadata;
191 3         155 });
192             }
193              
194             =head1 SPONSORS
195              
196             This code was paid for by
197              
198             =over 2
199              
200             =item *
201              
202             Perceptyx L
203              
204             =item *
205              
206             Shadowcat Systems L
207              
208             =back
209              
210             =head1 AUTHOR
211              
212             Paul Evans
213              
214             =cut
215              
216             0x55AA;