File Coverage

blib/lib/DBR/Handle.pm
Criterion Covered Total %
statement 58 89 65.1
branch 15 44 34.0
condition 1 9 11.1
subroutine 14 17 82.3
pod 3 10 30.0
total 91 169 53.8


line stmt bran cond sub pod time code
1             # the contents of this file are Copyright (c) 2004-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::Handle;
7              
8 18     18   99 use strict;
  18         40  
  18         677  
9 18     18   104 use base 'DBR::Common';
  18         34  
  18         12051  
10 18     18   9934 use DBR::Query;
  18         66  
  18         632  
11 18     18   12403 use DBR::Interface::Object;
  18         71  
  18         2389  
12 18     18   12667 use DBR::Interface::DBRv1;
  18         72  
  18         23785  
13             our $AUTOLOAD;
14              
15             sub new {
16 636     636 0 2523 my( $package ) = shift;
17 636         2823 my %params = @_;
18              
19 636         6294 my $self = {
20             conn => $params{conn},
21             session => $params{session},
22             instance => $params{instance}
23             };
24              
25 636         3314 bless( $self, $package );
26              
27 636 50       10844 return $self->_error( 'conn object is required' ) unless $self->{conn};
28 636 50       1999 return $self->_error( 'instance parameter is required' ) unless $self->{instance};
29              
30 636         4503 $self->{schema} = $self->{instance}->schema();
31 636 50       12650 return $self->_error( 'failed to retrieve schema' ) unless defined($self->{schema}); # schema is not required
32              
33             # Temporary solution to interfaces
34 636 50       7653 $self->{dbrv1} = DBR::Interface::DBRv1->new(
35             session => $self->{session},
36             instance => $self->{instance},
37             ) or return $self->_error('failed to create DBRv1 interface object');
38              
39 636         5007 return( $self );
40             }
41              
42 497     497 0 19943 sub select{ my $self = shift; return $self->{dbrv1}->select(@_) }
  497         2648  
43 494     494 0 1042 sub insert{ my $self = shift; return $self->{dbrv1}->insert(@_) }
  494         3018  
44 46     46 0 86 sub update{ my $self = shift; return $self->{dbrv1}->update(@_) }
  46         934  
45 1     1 0 713 sub delete{ my $self = shift; return $self->{dbrv1}->delete(@_) }
  1         9  
46              
47             sub AUTOLOAD {
48 42     42   34325 my $self = shift;
49 42         104 my $method = $AUTOLOAD;
50              
51 42         105 my @params = @_;
52              
53 42         296 $method =~ s/.*:://;
54 42 50       430 return unless $method =~ /[^A-Z]/; # skip DESTROY and all-cap methods
55 42 50       502 return $self->_error("Cannot autoload '$method' when no schema is defined") unless $self->{schema};
56              
57 42 50       16791 my $table = $self->{schema}->get_table( $method ) or return $self->_error("no such table '$method' exists in this schema");
58              
59 42 50       647 my $object = DBR::Interface::Object->new(
60             session => $self->{session},
61             instance => $self->{instance},
62             table => $table,
63             ) or return $self->_error('failed to create query object');
64              
65 42         331 return $object;
66             }
67              
68             sub begin{
69 17     17 1 42 my $self = shift;
70              
71 17 50       85 return $self->_error('Already transaction - cannot begin') if $self->{'_intran'};
72              
73 17         53 my $conn = $self->{conn};
74              
75 17 50 33     215 if ( $conn->b_intrans && !$conn->b_nestedTrans ){ # No nested transactions
76 0         0 $self->_logDebug('BEGIN - Fake');
77 0         0 $self->{'_faketran'} = $self->{'_intran'} = 1; #already in transaction, we are not doing a real begin
78 0         0 return 1;
79             }
80              
81 17 50       235 $conn->begin or return $self->_error('Failed to begin transaction');
82              
83 17         61 $self->{'_intran'} = 1;
84 17         61 return 1;
85              
86             }
87             sub commit{
88 17     17 1 44 my $self = shift;
89 17 50       92 return $self->_error('Not in transaction - cannot commit') unless $self->{'_intran'};
90              
91 17         51 my $conn = $self->{conn};
92              
93 17 50       86 if($self->{'_faketran'}){
94 0         0 $self->_logDebug('COMMIT - Fake');
95 0         0 $self->{'_faketran'} = $self->{'_intran'} = 0;
96              
97 0         0 return 1;
98             }
99              
100 17 50       230 $conn->commit or return $self->_error('Failed to commit transaction');
101              
102 17         81 $self->{'_intran'} = 0;
103 17         109 return 1;
104             }
105              
106             sub rollback{
107 0     0 1 0 my $self = shift;
108 0 0       0 return $self->_error('Not in transaction - cannot rollback') unless $self->{'_intran'};
109              
110 0         0 my $conn = $self->{conn};
111 0 0       0 if($self->{'_faketran'}){
112              
113 0         0 $self->_logDebug('ROLLBACK - Fake');
114 0         0 $self->{'_faketran'} = $self->{'_intran'} = 0;
115              
116 0         0 return 1;
117             }
118              
119 0 0       0 $conn->rollback or return $self->_error('Failed to roll back transaction');
120              
121 0         0 $self->{'_intran'} = 0;
122 0         0 return 1;
123             }
124              
125             sub getserial{
126 0     0 0 0 my $self = shift;
127 0         0 my $name = shift;
128 0   0     0 my $table = shift || 'serials';
129 0   0     0 my $field1 = shift || 'name';
130 0   0     0 my $field2 = shift || 'serial';
131 0 0       0 return $self->_error('name must be specified') unless $name;
132              
133 0         0 $self->begin();
134              
135 0         0 my $row = $self->select(
136             -table => $table,
137             -field => $field2,
138             -where => {$field1 => $name},
139             -single => 1,
140             -lock => 'update',
141             );
142              
143 0 0       0 return $self->_error('serial select failed') unless defined($row);
144 0 0       0 return $self->_error('serial is not primed') unless $row;
145              
146 0         0 my $id = $row->{$field2};
147              
148 0 0       0 return $self->_error('serial update failed') unless
149             $self->update(
150             -table => $table,
151             -fields => {$field2 => ['d',$id + 1]},
152             -where => {
153             $field1 => $name
154             },
155             );
156              
157 0         0 $self->commit();
158              
159 0         0 return $id;
160             }
161              
162 0     0 0 0 sub disconnect { 1 } # Dummy
163              
164             sub DESTROY{
165 636     636   8237 my $self = shift;
166              
167 636 50       13859 $self->rollback() if $self->{'_intran'};
168              
169             }
170              
171              
172             =pod
173              
174             =head1 NAME
175              
176             DBR::Handle
177              
178             =head1 SYNOPSIS
179              
180             Represents a connection to a specific instance of a DBR schema
181            
182             use DBR ( conf => '/path/to/my/DBR.conf' );
183             my $handle = dbr_connect('music');
184              
185             $handle->begin;
186            
187             my $resultset = $handle->mytable->where( myfield => 'somevalue' );
188             my $record = $resultset->next;
189             print $record->myfield;
190             $record->myfield('somenewvalue');
191            
192             $handle->commit;
193              
194             Note: Do not pass DBR handles around, especially if you are using transactions. Auto rollback is associated with the handle going out of scope.
195              
196             =head1 METHODS
197              
198             =head2 begin
199              
200             Begin a transaction;
201              
202             $handle->begin();
203              
204             =head2 commit
205              
206             Commit a transaction
207              
208             $handle->commit();
209              
210             =head2 rollback
211              
212             Roll back an open transaction
213              
214             $handle->rollback();
215            
216             NOTE: any open transactions are automatically rolled back when the handle goes out of scope
217              
218             =head2 AUTOLOAD
219              
220             The handle object is aware of all tables in the associated DB schema,
221             therefore all tables are available as virtual methods of a given handle.
222              
223             This is the primary way of gettig a table object.
224              
225             Some examples:
226            
227             # Deconstructed example:
228            
229             my $mytable = $handle->mytable;
230             my $resultsetAll = $mytable->all;
231             my $resultsetSome = $mytable->where( somefield => 'whatever' );
232              
233             # More normal example:
234            
235             my $resultsetSome = $handle->mytable->where( somefield => 'whatever' );
236             where ( my $record = $resultsetSome->next ){
237             print $record->somefield . "\n";
238             }
239              
240             =cut
241              
242              
243              
244             1;