File Coverage

blib/lib/PGObject/Type/Composite.pm
Criterion Covered Total %
statement 64 83 77.1
branch 8 26 30.7
condition 3 13 23.0
subroutine 11 13 84.6
pod n/a
total 86 135 63.7


line stmt bran cond sub pod time code
1             package PGObject::Type::Composite;
2              
3 5     5   17051 use 5.010;
  5         20  
4 5     5   27 use Scalar::Util;
  5         11  
  5         240  
5 5     5   2118 use PGObject;
  5         18957  
  5         29  
6 5     5   2168 use PGObject::Util::Catalog::Types qw(get_attributes);
  5         1816  
  5         253  
7 5     5   1841 use PGObject::Util::PseudoCSV;
  5         7128  
  5         301  
8 5     5   31 use Carp;
  5         10  
  5         3162  
9              
10             =head1 NAME
11              
12             PGObject::Type::Composite - Composite Type handler for PGObject
13              
14             =head1 VERSION
15              
16             Version 1
17              
18             =cut
19              
20             our $VERSION = 1.000000;
21              
22              
23             =head1 SYNOPSIS
24              
25             package MyObject;
26             use Moo;
27             with 'PGObject::Type::Composite';
28              
29             Then
30              
31             use MyObject;
32             my $dbh = DBI->connect;
33             MyObject->initialize(dbh => $dbh);
34             MyObject->register(registry => 'default', type => 'foo');
35              
36             And now every column of type foo (which must be a composite type) will get
37             deserialized into MyObject.
38              
39             =head1 EXPORTS
40              
41             =over
42              
43             =item initialize
44              
45             =item from_db
46              
47             =item to_db
48              
49             =back
50              
51             =cut
52              
53             =head1 SUBROUTINES/METHODS
54              
55             =head2 initialize
56              
57             =head2 register
58              
59             =head2 from_db
60              
61             =head2 to_db
62              
63             =cut
64              
65             sub import {
66 5     5   50 my ($importer) = caller;
67 5         12 my @cols;
68 5 50       10 my $can_has if *{ "${importer}::has" }; # moo/moose lolmoose?
  5         41  
69              
70             my $initialize = sub {
71 3     3   78 my ($pkg, %args) = @_;
72 3 50       14 croak 'first argument must be a package name' if ref $pkg;
73             croak 'Must supply a dbh or columns argument'
74 3 50 50     22 unless $args{dbh} or scalar @{$args{columns}};
  3         16  
75              
76 3 50       8 @cols = @{$args{columns}} if @{$args{columns}};
  3         14  
  3         14  
77 3 50 33     16 if ($args{dbh} and !@cols){
78             @cols = get_attributes(
79             typeschema => "$pkg"->_get_schema,
80             typename => "$pkg"->_get_typename,
81             dbh => $args{dbh}
82 0         0 );
83             }
84 3         24 return @cols;
85 5         77 };
86              
87             my $from_db = sub {
88 6     6   18 my ($to_pkg, $string) = @_;
89 6         17 my $hashref = pcsv2hash($string, map { $_->{attname}} @cols);
  18         75  
90 6 50       612 if ($PGObject::VERSION =~ /^1./){
91             $hashref = {
92 6         14 map { $_->{attname} => PGObject::process_type(
93             $hashref->{$_->{attname}},
94             $_->{atttype},
95 18 50       153 (eval {$to_pkg->can('_get_registry')} ?
  18         99  
96             "$to_pkg"->_get_registry :
97             'default'))
98             } @cols
99             };
100             } else {
101             $hashref = {
102 0         0 map { $_->{attname} => PGObject::Type::Registry->deserialize(
103             dbstring => $hashref->{$_->{attname}},
104             dbtype => $_->{atttype},
105             registry =>
106 0 0       0 (eval {$to_pkg->can('_get_registry')} ?
  0         0  
107             "$to_pkg"->_get_registry :
108             'default'))
109             } @cols
110             };
111             }
112 6 50       76 if ($can_has){ # moo/moose
113 0         0 return "$pkg"->new(%$hashref);
114             } else {
115 6         30 return bless($hashref, $to_pkg);
116             }
117 5         19 };
118              
119             my $to_db = sub {
120 3     3   942 my ($self) = @_;
121             my $hashref = { map {
122 3         8 my $att = $_->{attname};
  9         14  
123 9   33     16 my $val = eval { $self->$att } || $self->{$att};
124 9         28 $att => $val;
125             } @cols };
126             return {
127             type => $typename,
128 3         8 value => hash2pcsv($hashref, map {$_->{attname}} @cols),
  9         25  
129             };
130 5         15 };
131              
132             my $register = sub { # easier here than also doing export
133 0     0   0 my $self = shift @_;
134 0 0       0 croak "Can't pass reference to register \n".
135             "Hint: use the class instead of the object" if ref $self;
136 0         0 my %args = @_;
137 0         0 my $registry = $args{registry};
138 0   0     0 $registry ||= 'default';
139 0         0 my $types = $args{types};
140 0 0 0     0 croak 'Must supply types as arrayref'
141             unless defined $types and @$types;
142 0         0 for my $type (@$types){
143 0 0       0 if ($PGObject::VERSION =~ /^1./){
144 0         0 my $ret =
145             PGObject->register_type(registry => $registry,
146             pg_type => $type,
147             perl_class => "$self");
148 0 0       0 return $ret unless $ret;
149             } else {
150 0         0 my $ret =
151             PGObject::Type::Registry->register_type(
152             registry => $registry,
153             dbtype => $type,
154             apptype => "$self");
155             }
156 0         0 return 1;
157             }
158 5         15 };
159             my $_get_cols = sub {
160 0     0   0 return @cols;
161 5         15 };
162              
163 5     5   36 no strict 'refs';
  5         9  
  5         505  
164 5         11 *{ "${importer}::initialize" } = $initialize;
  5         33  
165 5         9 *{ "${importer}::register" } = $register;
  5         19  
166 5         12 *{ "${importer}::from_db" } = $from_db;
  5         17  
167 5         11 *{ "${importer}::to_db" } = $to_db;
  5         19  
168 5         10 *{ "${importer}::_get_cols" } = $_get_cols;
  5         173  
169             }
170              
171             =head1 AUTHOR
172              
173             Chris Travers, C<< >>
174              
175             =head1 BUGS
176              
177             Please report any bugs or feature requests to C, or through
178             the web interface at L. I will be notified, and then you'll
179             automatically be notified of progress on your bug as I make changes.
180              
181              
182              
183              
184             =head1 SUPPORT
185              
186             You can find documentation for this module with the perldoc command.
187              
188             perldoc PGObject::Type::Composite
189              
190              
191             You can also look for information at:
192              
193             =over 4
194              
195             =item * RT: CPAN's request tracker (report bugs here)
196              
197             L
198              
199             =item * AnnoCPAN: Annotated CPAN documentation
200              
201             L
202              
203             =item * CPAN Ratings
204              
205             L
206              
207             =item * Search CPAN
208              
209             L
210              
211             =back
212              
213              
214             =head1 ACKNOWLEDGEMENTS
215              
216              
217             =head1 LICENSE AND COPYRIGHT
218              
219             Copyright 2014 Chris Travers.
220              
221             This program is distributed under the (Revised) BSD License:
222             L
223              
224             Redistribution and use in source and binary forms, with or without
225             modification, are permitted provided that the following conditions
226             are met:
227              
228             * Redistributions of source code must retain the above copyright
229             notice, this list of conditions and the following disclaimer.
230              
231             * Redistributions in binary form must reproduce the above copyright
232             notice, this list of conditions and the following disclaimer in the
233             documentation and/or other materials provided with the distribution.
234              
235             * Neither the name of Chris Travers's Organization
236             nor the names of its contributors may be used to endorse or promote
237             products derived from this software without specific prior written
238             permission.
239              
240             THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
241             "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
242             LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
243             A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
244             OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
245             SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
246             LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
247             DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
248             THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
249             (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
250             OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
251              
252              
253             =cut
254              
255             1; # End of PGObject::Type::Composite