File Coverage

blib/lib/DBIx/Roles/Buffered.pm
Criterion Covered Total %
statement 52 53 98.1
branch 12 20 60.0
condition 11 17 64.7
subroutine 10 10 100.0
pod 1 7 14.2
total 86 107 80.3


line stmt bran cond sub pod time code
1             # $Id: Buffered.pm,v 1.3 2005/11/29 11:55:01 dk Exp $
2              
3             package DBIx::Roles::Buffered;
4              
5             # Saves do() and selectrow_array() in a buffer, calls these as a single query later.
6             # Useful with lots of UPDATES and INSERTS over connections with high latency
7              
8 1     1   5 use strict;
  1         1  
  1         32  
9 1     1   5 use vars qw(%defaults $VERSION);
  1         2  
  1         694  
10              
11             $VERSION = '1.00';
12              
13             %defaults = (
14             Buffered => 1,
15             BufferLimit => 16384,
16             );
17              
18             sub initialize
19             {
20             return {
21 3     3 0 27 buffer => [],
22             params => [],
23             curr => 0,
24             lock => 0,
25             }, \%defaults, qw(flush);
26             }
27              
28             sub dbi_method
29             {
30 13     13 0 40 my ( $self, $storage, $method, @params) = @_;
31              
32 13 100 100     180 return $self-> super( $method, @params) if
      33        
      66        
33             $storage-> {lock} or
34             not $self->{attr}->{Buffered} or
35             ( $method ne 'do' and $method ne 'selectrow_array');
36 1         3 my ( $query, $attr_hash) = ( shift @params, shift @params);
37              
38 1 50 50     8 die "Fatal: DBIx::Roles::Buffered does not implement \%attr passed to DBI methods\n"
39             if $attr_hash and scalar keys %$attr_hash;
40            
41 1         3 my $length = length($query);
42 1         6 $length += 2 + length $_ for @params;
43              
44 1 50 33     17 flush( $self, $storage) if
45             $self-> {attr}-> {BufferLimit} and
46             $length + $storage-> {curr} > $self-> {attr}-> {BufferLimit};
47              
48 1         8 my $expected = scalar( @_ = $query =~ m/\?/g );
49 1 50       6 die "Query '$query' contains references to $expected parameters, got ",
50             scalar(@params), " passed\n"
51             if $expected != @params;
52              
53 1         2 push @{$storage-> {buffer}}, $query;
  1         4  
54 1         2 push @{$storage-> {params}}, @params;
  1         5  
55 1         3 $storage-> {curr} += $length;
56              
57 1 50       11 return ( $method eq 'do') ? "0E0" : ();
58             }
59              
60             sub flush
61             {
62 11     11 1 22 my ( $self, $storage, $discard) = @_;
63 11 100       35 return unless $storage-> {curr};
64              
65             # clear the internal state to be re-entrant
66 1         11 my $q = join(';', @{$storage->{buffer}});
  1         5  
67 1         2 my @p = @{$storage->{params}};
  1         5  
68 1         2 @{$storage->{buffer}} = ();
  1         3  
69 1         3 @{$storage->{params}} = ();
  1         3  
70 1         2 $storage-> {curr} = 0;
71              
72 1         3 local $storage->{lock} = 1;
73 1 50       14 $self-> do( $q, {}, @p) unless $discard;
74             }
75              
76             sub begin_work
77             {
78 2     2 0 5 my ( $self, $storage) = @_;
79 2         9 flush( $self, $storage);
80 2         6 return $self-> super;
81             }
82              
83             sub rollback
84             {
85 2     2 0 3 my ( $self, $storage) = @_;
86 2         6 flush( $self, $storage, 1);
87 2         7 return $self-> super;
88             }
89              
90             sub commit
91             {
92 1     1 0 3 my ( $self, $storage) = @_;
93 1         4 flush( $self, $storage);
94 1         12 return $self-> super;
95             }
96              
97             sub disconnect
98             {
99 3     3 0 5 my ( $self, $storage) = @_;
100 3         11 flush( $self, $storage);
101 3         9 return $self-> super;
102             }
103              
104             sub STORE
105             {
106 17     17   32 my ( $self, $storage, $key, $val) = @_;
107              
108 17 100 100     74 if ( $key eq 'Buffered' and not $val) {
    50          
109 3         7 $self-> {attr}-> {Buffered} = 0;
110 3         11 flush( $self, $storage);
111             } elsif ( $key eq 'BufferLimit') {
112 0 0       0 die "Fatal: 'BufferLimit' must be a positive integer"
113             unless $val =~ /^\d+$/;
114             }
115              
116 17         46 return $self-> super( $key, $val);
117             }
118              
119             1;
120              
121             __DATA__