File Coverage

blib/lib/DBR/Interface/Object.pm
Criterion Covered Total %
statement 87 118 73.7
branch 28 78 35.9
condition n/a
subroutine 15 17 88.2
pod 7 7 100.0
total 137 220 62.2


line stmt bran cond sub pod time code
1             # the contents of this file are Copyright (c) 2009 Daniel Norman
2             # This program is free software; you can redistribute it and/or
3             # modify it under the terms of the GNU General Public License as
4             # published by the Free Software Foundation.
5              
6             package DBR::Interface::Object;
7              
8 18     18   105 use strict;
  18         34  
  18         732  
9 18     18   188 use base 'DBR::Common';
  18         37  
  18         3544  
10 18     18   9126 use DBR::Config::Scope;
  18         65  
  18         514  
11 18     18   10116 use DBR::ResultSet::Empty;
  18         56  
  18         526  
12 18     18   13149 use DBR::Query::Select;
  18         69  
  18         569  
13 18     18   13871 use DBR::Query::Insert;
  18         52  
  18         1452  
14 18     18   14679 use DBR::Interface::Where;
  18         59  
  18         863  
15 18     18   176 use DBR::ResultSet;
  18         40  
  18         433  
16 18     18   109 use Carp;
  18         44  
  18         1905  
17              
18             use constant ({
19 18         40464 EMPTY => bless( [], 'DBR::ResultSet::Empty'),
20             DUMMY => bless( [], 'DBR::Misc::Dummy'),
21 18     18   107 });
  18         41  
22              
23             sub new {
24 42     42 1 724 my( $package ) = shift;
25 42         190 my %params = @_;
26 42         244 my $self = {
27             session => $params{session},
28             instance => $params{instance},
29             table => $params{table},
30             };
31              
32 42         149 bless( $self, $package );
33              
34 42 50       282 return $self->_error('table object must be specified') unless ref($self->{table}) eq 'DBR::Config::Table';
35 42 50       168 return $self->_error('instance object must be specified') unless $self->{instance};
36              
37 42         503 return( $self );
38             }
39              
40             sub all{
41 15     15 1 30 my $self = shift;
42              
43 15         44 my $table = $self->{table};
44 15 50       95 my $scope = DBR::Config::Scope->new(
45             session => $self->{session},
46             conf_instance => $table->conf_instance,
47             extra_ident => $table->name,
48             ) or return $self->_error('Failed to get calling scope');
49              
50 15 50       119 my $pk = $table->primary_key or return $self->_error('Failed to fetch primary key');
51 15 50       94 my $prefields = $scope->fields or return $self->_error('Failed to determine fields to retrieve');
52              
53 15         35 my %uniq;
54 15         43 my @fields = grep { !$uniq{ $_->field_id }++ } (@$pk, @$prefields);
  20         104  
55              
56 15 50       131 my $query = DBR::Query::Select->new(
57             session => $self->{session},
58             instance => $self->{instance},
59             scope => $scope,
60             fields => \@fields,
61             tables => $table,
62             ) or return $self->_error('failed to create Query object');
63              
64 15         414 my $resultset = DBR::ResultSet->new( $query );
65              
66 15         105 return $resultset;
67             }
68              
69             sub where{
70 12     12 1 27 my $self = shift;
71 12         38 my @inwhere = @_;
72              
73 12         36 my $table = $self->{table};
74 12 50       79 my $scope = DBR::Config::Scope->new(
75             session => $self->{session},
76             conf_instance => $table->conf_instance,
77             extra_ident => $table->name,
78             ) or return $self->_error('Failed to get calling scope');
79              
80              
81              
82 12 50       113 my $pk = $table->primary_key or return $self->_error('Failed to fetch primary key');
83 12 50       84 my $prefields = $scope->fields or return $self->_error('Failed to determine fields to retrieve');
84              
85 12         28 my %uniq;
86 12         37 my @fields = grep { !$uniq{ $_->field_id }++ } (@$pk, @$prefields);
  14         83  
87              
88              
89 12 50       160 my $builder = DBR::Interface::Where->new(
90             session => $self->{session},
91             instance => $self->{instance},
92             primary_table => $table,
93 0         0 ) or return $self->_error("Failed to generate where for ${\$table->name}");
94              
95 12         151 my $where = $builder->build( \@inwhere );
96              
97 12 50       163 return EMPTY if $where->is_emptyset;
98              
99 12         49 my $alias = $table->alias;
100 12 100       59 if($alias){
101 2         5 map { $_->table_alias($alias) } @fields;
  4         13  
102             }
103              
104 12 50       152 my $query = DBR::Query::Select->new(
105             session => $self->{session},
106             instance => $self->{instance},
107             scope => $scope,
108             fields => \@fields ,
109             tables => $builder->tables,
110             where => $where,
111             builder => $builder,
112             ) or croak('failed to create Query object');
113              
114 12         2558 my $resultset = DBR::ResultSet->new( $query );
115              
116 12         118 return $resultset;
117             }
118              
119              
120             sub insert {
121 5     5 1 12 my $self = shift;
122 5         18 my %fields = @_;
123              
124 5         11 my $table = $self->{table};
125 5         8 my @sets;
126              
127 5         17 foreach my $fieldname (keys %fields){
128              
129 7 50       30 my $field = $table->get_field( $fieldname ) or croak "invalid field $fieldname";
130 7 50       34 my $value = $field->makevalue( $fields{ $fieldname } ) or croak "failed to build value object for $fieldname";
131              
132 5 50       38 my $set = DBR::Query::Part::Set->new($field,$value) or confess 'failed to create set object';
133 5         18 push @sets, $set;
134             }
135              
136 3 50       32 my $query = DBR::Query::Insert->new(
137             instance => $self->{instance},
138             session => $self->{session},
139             sets => \@sets,
140             tables => $table,
141             ) or confess 'failed to create query object';
142              
143 2         14 return $query->run( void => !defined(wantarray) );
144             }
145              
146              
147             #Fetch by Primary key
148             sub get{
149 0     0 1 0 my $self = shift;
150 0         0 my $pkval = shift;
151 0 0       0 croak('get only accepts one argument. Use an arrayref to specify multiple pkeys.') if shift;
152              
153 0         0 my $table = $self->{table};
154 0 0       0 my $pk = $table->primary_key or return $self->_error('Failed to fetch primary key');
155 0 0       0 scalar(@$pk) == 1 or return $self->_error('the get method can only be used with a single field pkey');
156 0         0 my $field = $pk->[0];
157              
158 0 0       0 my $scope = DBR::Config::Scope->new(
159             session => $self->{session},
160             conf_instance => $table->conf_instance,
161             extra_ident => $table->name,
162             ) or return $self->_error('Failed to get calling scope');
163              
164 0 0       0 my $prefields = $scope->fields or return $self->_error('Failed to determine fields to retrieve');
165              
166 0         0 my %uniq;
167 0         0 my @fields = grep { !$uniq{ $_->field_id }++ } (@$pk, @$prefields);
  0         0  
168              
169 0 0       0 my $value = $field->makevalue( $pkval ) or return $self->_error("failed to build value object for ${\$field->name}");
  0         0  
170              
171 0 0       0 return ref($pkval) ? EMPTY : DUMMY if $value->is_emptyset;
    0          
172              
173 0 0       0 my $outwhere = DBR::Query::Part::Compare->new( field => $field, value => $value ) or return $self->_error('failed to create compare object');
174              
175 0 0       0 my $query = DBR::Query::Select->new(
176             session => $self->{session},
177             instance => $self->{instance},
178             fields => \@fields,
179             tables => $table,
180             where => $outwhere,
181             scope => $scope,
182             ) or return $self->_error('failed to create Query object');
183              
184 0         0 my $resultset = DBR::ResultSet->new( $query );
185              
186 0 0       0 if(ref($pkval)){
187 0         0 return $resultset;
188             }else{
189 0         0 return $resultset->next;
190             }
191             }
192              
193             sub enum{
194 0     0 1 0 my $self = shift;
195 0         0 my $fieldname = shift;
196              
197 0         0 my $table = $self->{table};
198 0 0       0 my $field = $table->get_field( $fieldname ) or return $self->_error("invalid field $fieldname");
199              
200 0 0       0 my $trans = $field->translator or return $self->_error("Field '$fieldname' has no translator");
201 0 0       0 $trans->module eq 'Enum' or return $self->_error("Field '$fieldname' is not an enum");
202              
203 0 0       0 my $opts = $trans->options or return $self->_error('Failed to get opts');
204              
205 0 0       0 return wantarray?@{$opts}:$opts;
  0         0  
206             }
207              
208              
209             sub parse{
210 10     10 1 22 my ($self, $fieldname, $value) = @_;
211              
212 10 50       39 my $field = $self->{table}->get_field( $fieldname ) or croak "Invalid field $fieldname";
213 10         32 my $trans = $field->translator;
214              
215 10 100       31 if($trans){
216 4         25 my $obj = $trans->parse( $value );
217 4 50       33 defined($obj) || return $self->_error("Invalid value " .
    100          
218             ( defined($value) ? "'$value'" : '(undef)' ) .
219             " for " . $field->name );
220 2         29 return $obj;
221             }else{
222 6 100       21 $field->testsub->($value) || return $self->_error("Invalid value " .
    100          
223             ( defined($value) ? "'$value'" : '(undef)' ) .
224             " for " . $field->name );
225 2         13 return $value;
226             }
227             }
228              
229             1;
230              
231             __END__
232              
233             =pod
234              
235             =head1 NAME
236              
237             DBR::Interface::Object
238             An object representing a table about to be queried. This object is the entry point for executing queries against a given table
239              
240             =head1 SYNOPSIS
241              
242             $dbrh->tableA->all();
243             $dbrh->tableA->get( $primary_key );
244             $dbrh->tableA->where( field => 'value' );
245             $dbrh->tableA->where( 'relationshipB.field' => 'value' );
246              
247             =head1 Methods
248              
249              
250             =head2 B<new>
251              
252             Constructor for DBR::Interface::Object -
253             Called by DBR::Handle->tablename (autoloaded)
254              
255             =head2 B<where>
256              
257             Initiates a database query based on provided constraints.
258              
259             Arguments: Key value pairs of relationships/fields and values.
260              
261             Returns: DBR::Query::ResultSet object containing resultant query
262              
263             # Simple use case:
264             $dbrh->tableA->where( fieldname => $somevalue );
265              
266             # Constrain by related data:
267             $dbrh->tableA->where( 'relationshipB.fieldX' => $somevalue );
268              
269             # Constrain by more related data:
270             $dbrh->tableA->where(
271             'relB.fieldX' => 'value',
272             'relB.fieldY' => $somevalue, # same relationship twice, different fields - do the right thing
273             'relC.relD.relE.fieldZ' => $far_removed_value, # ...ad infinitum
274             );
275              
276              
277             By default, equality comparisons are assumed. ( field = 'value')
278             For other types of comparisons:
279              
280             use DBR::Util::Operator; # Imports operators into your scope
281             $dbrh->tableA->where( fieldname => NOT 'value' );
282             $dbrh->tableA->where( fieldname => GT 123 );
283             $dbrh->tableA->where( fieldname => LT 123 );
284             $dbrh->tableA->where( fieldname => LIKE 'value%' );
285             # And so on
286              
287             For more details, See: L<DBR::Util::Operator>
288              
289              
290              
291             =head2 B<get>
292              
293             Initiates a database queryFetch all rows from a given table.
294              
295             Arguments: single scalar value, or one arrayref of primary key ids.
296              
297             my $single_record = $dbrh->tablename->get( 123 ); # pkey 123
298             my $resultset_obj = $dbrh->tablename->get( [ 123, 456 ] );
299              
300             If given arrayref, Returns a single L<DBR::Query::ResultSet> object containing resultant query
301              
302             If given single value, Returns a single L<DBR::Query::Record> object (dynamically created)
303              
304              
305             =head2 B<all>
306              
307             Initiates a database query with NO constraints. Fetch all rows from a given table.
308              
309             Arguments: None
310              
311             Returns: L<DBR::Query::ResultSet> object containing resultant query
312              
313             =head2 B<insert>
314              
315             =head2 B<enum>
316              
317             =head2 B<parse>
318              
319             =cut