File Coverage

blib/lib/DR/Tarantool/Tuple.pm
Criterion Covered Total %
statement 66 71 92.9
branch 26 40 65.0
condition 6 18 33.3
subroutine 14 15 93.3
pod 6 6 100.0
total 118 150 78.6


line stmt bran cond sub pod time code
1 7     7   707 use utf8;
  7         10  
  7         37  
2 7     7   177 use strict;
  7         7  
  7         180  
3 7     7   23 use warnings;
  7         7  
  7         219  
4              
5             =head1 NAME
6              
7             DR::Tarantool::Tuple - a tuple container for L
8              
9             =head1 SYNOPSIS
10              
11             my $tuple = new DR::Tarantool::Tuple([ 1, 2, 3]);
12             my $tuple = new DR::Tarantool::Tuple([ 1, 2, 3], $space);
13             my $tuple = unpack DR::Tarantool::Tuple([ 1, 2, 3], $space);
14              
15              
16             $tuple->next( $other_tuple );
17              
18             $f = $tuple->raw(0);
19              
20             $f = $tuple->name_field;
21              
22              
23             =head1 DESCRIPTION
24              
25             A tuple contains normalized (unpacked) fields. You can access the fields
26             by their indexes (see L function) or by their names (if they are
27             described in the space).
28              
29             Each tuple can contain references to L tuple and Lator,
30             so that if the server returns more than one tuple, all of them
31             can be accessed.
32              
33             =head1 METHODS
34              
35             =cut
36              
37             package DR::Tarantool::Tuple;
38 7     7   2298 use DR::Tarantool::Iterator;
  7         12  
  7         229  
39 7     7   42 use Scalar::Util 'weaken', 'blessed';
  7         7  
  7         501  
40 7     7   29 use Carp;
  7         8  
  7         4896  
41             $Carp::Internal{ (__PACKAGE__) }++;
42              
43              
44             =head2 new
45              
46             A constructor.
47              
48             my $t = DR::Tarantool::Tuple->new([1, 2, 3]);
49             my $t = DR::Tarantool::Tuple->new([1, 2, 3], $space);
50              
51             =cut
52              
53             sub new :method {
54 7     7 1 9 my ($class, $tuple, $space) = @_;
55              
56 7 50       12 $class = ref $class if ref $class;
57              
58             # hack to replace default autoload
59 7 50 33     39 $class = $space->tuple_class if $space and $class eq __PACKAGE__;
60              
61 7 50 33     43 croak 'wrong space' if defined $space and !blessed $space;
62              
63 7 50       16 croak 'tuple must be ARRAYREF [of ARRAYREF]' unless 'ARRAY' eq ref $tuple;
64 7 50       12 croak "tuple can't be empty" unless @$tuple;
65              
66 7 100       18 $tuple = [ $tuple ] unless 'ARRAY' eq ref $tuple->[0];
67              
68 7   33     37 my $iterator = DR::Tarantool::Iterator->new(
69             $tuple,
70             data => $space,
71             item_class => ref($class) || $class,
72             item_constructor => '_new'
73             );
74              
75 7   33     42 return bless {
76             idx => 0,
77             iterator => $iterator,
78             } => ref($class) || $class;
79             }
80              
81              
82             sub _new {
83 16     16   18 my ($class, $item, $idx, $iterator) = @_;
84 16   33     118 return bless {
85             idx => $idx,
86             iterator => $iterator,
87             } => ref($class) || $class;
88             }
89              
90              
91             =head2 unpack
92              
93             Another way to construct a tuple.
94              
95             my $t = DR::Tarantool::Tuple->unpack([1, 2, 3], $space);
96              
97             =cut
98              
99             sub unpack :method {
100 1     1 1 2 my ($class, $tuple, $space) = @_;
101 1 50       5 croak 'wrong space' unless blessed $space;
102 1 50       6 return undef unless defined $tuple;
103 1 50       3 croak 'tuple must be ARRAYREF [of ARRAYREF]' unless 'ARRAY' eq ref $tuple;
104 1 50       3 return undef unless @$tuple;
105              
106 1 50       3 if ('ARRAY' eq ref $tuple->[0]) {
107 0         0 my @tu;
108              
109 0         0 push @tu => $space->unpack_tuple($_) for @$tuple;
110 0         0 return $class->new(\@tu, $space);
111             }
112              
113 1         3 return $class->new($space->unpack_tuple($tuple), $space);
114             }
115              
116              
117             =head2 raw
118              
119             Return raw data from the tuple.
120              
121             my $array = $tuple->raw;
122              
123             my $field = $tuple->raw(0);
124              
125             =cut
126              
127             sub raw :method {
128 37     37 1 1737 my ($self, $fno) = @_;
129              
130 37         98 my $item = $self->{iterator}->raw_item( $self->{idx} );
131              
132 37 100       68 return $item unless defined $fno;
133              
134 34 50       84 croak 'wrong field number' unless $fno =~ /^-?\d+$/;
135              
136 34 50       104 return undef if $fno < -@$item;
137 34 100       55 return undef if $fno >= @$item;
138 32         118 return $item->[ $fno ];
139             }
140              
141              
142             =head2 next
143              
144             Append or return the next tuple, provided there is more than one
145             tuple in the result set.
146              
147             my $next_tuple = $tuple->next;
148              
149             =cut
150              
151             sub next :method {
152              
153 5     5 1 8 my ($self, $tuple) = @_;
154              
155 5         7 my $iterator = $self->{iterator};
156 5         6 my $idx = $self->{idx} + 1;
157              
158             # if tuple is exists next works like 'iterator->push'
159 5 100       11 if ('ARRAY' eq ref $tuple) {
160 2         5 $iterator->push( $tuple );
161 2         3 $idx = $iterator->count - 1;
162             }
163              
164 5 50       8 return undef unless $idx < $iterator->count;
165              
166 5         15 my $next = bless {
167             idx => $idx,
168             iterator => $iterator,
169             } => ref($self);
170              
171 5         10 return $next;
172             }
173              
174              
175             =head2 iter
176              
177             Return an iterator object associated with the tuple.
178              
179              
180             my $iterator = $tuple->iter;
181              
182             my $iterator = $tuple->iter('MyTupleClass', 'new');
183              
184             while(my $t = $iterator->next) {
185             # the first value of $t and $tuple are the same
186             ...
187             }
188              
189             =head3 Arguments
190              
191             =over
192              
193             =item package (optional)
194              
195             =item method (optional)
196              
197             If 'package' and 'method' are present, $iterator->L method
198             constructs objects using C<< $package->$method( $next_tuple ) >>
199              
200             If 'method' is not present and 'package' is present, the iterator
201             blesses the raw array with 'package'.
202              
203             =back
204              
205             =cut
206              
207             sub iter :method {
208 6     6 1 255 my ($self, $class, $method) = @_;
209              
210 6         6 my $iterator = $self->{iterator};
211              
212 6 100       12 if ($class) {
213             return $self->{iterator}->clone(
214             item_class => $class,
215             item_constructor => sub {
216 6     6   8 my ($c, $item, $idx) = @_;
217              
218 6 100       9 if ($method) {
219 2         11 my $bitem = bless {
220             idx => $idx,
221             iterator => $iterator,
222             } => ref($self);
223              
224              
225 2         9 return $c->$method( $bitem );
226             }
227 4   33     33 return bless [ @$item ] => ref($c) || $c;
228             }
229 2         12 );
230             }
231              
232 4         10 return $self->{iterator};
233             }
234              
235              
236             =head2 tail
237              
238             Return the tail of the tuple (array of unnamed fields). The function always
239             returns B (as L).
240              
241             =cut
242              
243             sub tail {
244 1     1 1 2 my ($self) = @_;
245 1         3 my $space = $self->{iterator}->data;
246 1         2 my $raw = $self->raw;
247              
248 1 50       5 return [ @$raw[ $space->tail_index .. $#$raw ] ] if $space;
249 0           return $raw;
250             }
251              
252              
253              
254 0     0     sub DESTROY { }
255              
256              
257             =head1 COPYRIGHT AND LICENSE
258              
259             Copyright (C) 2011 Dmitry E. Oboukhov
260             Copyright (C) 2011 Roman V. Nikolaev
261              
262             This program is free software, you can redistribute it and/or
263             modify it under the terms of the Artistic License.
264              
265             =head1 VCS
266              
267             The project is placed git repo on github:
268             L.
269              
270             =cut
271              
272             1;