| 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; |