File Coverage

blib/lib/DBIx/SimpleQuery.pm
Criterion Covered Total %
statement 37 116 31.9
branch 10 60 16.6
condition 0 11 0.0
subroutine 10 16 62.5
pod 7 11 63.6
total 64 214 29.9


line stmt bran cond sub pod time code
1             ##
2             ## File: DBIx/SimpleQuery.pm
3             ## Author: Steve Simms
4             ##
5             ## Revision: $Revision$
6             ## Date: $Date$
7             ##
8             ## A module designed to take away the pain of querying the database.
9             ##
10              
11             package DBIx::SimpleQuery;
12              
13 3     3   61324 use Carp;
  3         7  
  3         259  
14 3     3   12321 use DBI;
  3         76001  
  3         219  
15 3     3   2194 use DBIx::SimpleQuery::Object;
  3         13  
  3         84  
16              
17 3     3   19 use strict;
  3         6  
  3         116  
18              
19             require Exporter;
20 3     3   15 use vars qw(@ISA @EXPORT);
  3         5  
  3         5106  
21             @ISA = qw(Exporter);
22             @EXPORT = qw(query qs);
23              
24             our $VERSION = "0.05";
25              
26             my $default_dsn;
27             my $default_user;
28             my $default_password;
29              
30             my $debug = 0;
31              
32             sub new {
33 6     6 1 11 my ($class, %params) = @_;
34 6         9 my $self = {};
35              
36             # A main goal of this module is to eliminate the need to specify
37             # user and password if they can be derived.
38             #
39             # Try to get connection information from the following sources,
40             # in decreasing order of preference:
41             #
42             # - Specified as arguments to query (defeats the point, but a
43             # useful override nonetheless)
44             # - Given as parameters to new, which may be called explicitly by
45             # the module, instead of implicitly by query.
46 6 50       18 if (keys %params) {
    50          
    0          
    0          
47 0         0 $self->{"dsn"} = $params{"dsn"};
48 0         0 $self->{"user"} = $params{"user"};
49 0         0 $self->{"password"} = $params{"password"};
50             }
51              
52             # - Stored as module-level variables
53             elsif ($default_dsn) {
54 6         12 $self->{"dsn"} = $default_dsn;
55 6         8 $self->{"user"} = $default_user;
56 6         9 $self->{"password"} = $default_password;
57             }
58              
59             # - Stored as environment variables
60             elsif ($ENV{"DBIX_SIMPLEQUERY_DSN"}) {
61 0         0 $self->{"dsn"} = $ENV{"DBIX_SIMPLEQUERY_DSN"};
62 0         0 $self->{"user"} = $ENV{"DBIX_SIMPLEQUERY_USER"};
63 0         0 $self->{"password"} = $ENV{"DBIX_SIMPLEQUERY_PASSWORD"};
64             }
65              
66             # - Read from /etc/simplequery.conf
67             elsif (-r '/etc/simplequery.conf') {
68 0         0 open my $config_file, '<', '/etc/simplequery.conf';
69 0         0 while (<$config_file>) {
70 0         0 chomp;
71 0         0 my $line = $_;
72            
73             # Skip Comments
74 0 0       0 next if $line =~ /^\#/;
75              
76             # Skip Blank Linkes
77 0 0       0 next if $line eq "";
78 0 0       0 next if $line =~ /^\s+$/;
79              
80             # All remaining lines should be configuration values
81 0 0       0 unless ($line =~ /^\s*(dsn|user|password)\s*=\s*(\S+)\s*$/) {
82 0         0 croak "Bad config file format: $line";
83             }
84             else {
85 0         0 $self->{$1} = $2;
86             }
87             }
88             }
89              
90             # - Default to the first available data source of the first
91             # available driver of Oracle, Pg, or mysql, in that order, using
92             # the current user's login name, and no password.
93             else {
94 0         0 my @available_drivers = DBI->available_drivers();
95 0         0 @available_drivers = grep { /^(?:Oracle|Pg|mysql)$/ } @available_drivers;
  0         0  
96 0         0 my @data_sources = DBI->data_sources(shift @available_drivers);
97              
98 0         0 $self->{"dsn"} = shift(@data_sources);
99 0         0 $self->{"user"} = getpwuid($>);
100 0         0 $self->{"password"} = "";
101             }
102              
103 6         16 return bless $self, $class;
104             }
105              
106 0     0 0 0 sub setDefaults { return set_defaults(@_); }
107             sub set_defaults {
108 2 100   2 1 18 my %defaults = (ref($_[0]) eq "HASH" ? %{$_[0]} : @_);
  1         4  
109 2 50       8 $default_dsn = $defaults{"dsn"} if exists $defaults{"dsn"};
110 2 50       7 $default_user = $defaults{"user"} if exists $defaults{"user"};
111 2 50       8 $default_password = $defaults{"password"} if exists $defaults{"password"};
112 2         5 return;
113             }
114              
115 0     0 0 0 sub getDsn { return get_dsn(@_); }
116             sub get_dsn {
117 2     2 1 6 my $self = shift();
118 2 50       13 $self = new DBIx::SimpleQuery unless (ref($self) eq "DBIx::SimpleQuery");
119 2         36 return $self->{"dsn"};
120             }
121              
122 0     0 0 0 sub getUser { return get_user(@_); }
123             sub get_user {
124 2     2 1 3 my $self = shift();
125 2 50       10 $self = new DBIx::SimpleQuery unless (ref($self) eq "DBIx::SimpleQuery");
126 2         11 return $self->{"user"};
127             }
128              
129 0     0 0 0 sub getPassword { return get_password(@_); }
130             sub get_password {
131 2     2 1 3 my $self = shift();
132 2 50       10 $self = new DBIx::SimpleQuery unless (ref($self) eq "DBIx::SimpleQuery");
133 2         9 return $self->{"password"};
134             }
135              
136             # This can be called either as a class method or a function
137             sub query {
138 0     0 1   my $self = shift();
139 0           my $query;
140            
141 0 0         if (ref($self) eq "DBIx::SimpleQuery") {
142 0           $query = shift();
143             }
144             else {
145 0           $query = $self;
146 0           $self = new DBIx::SimpleQuery(@_);
147             }
148            
149             # Establish the connection
150 0           my $dbh;
151 0 0         if ($self->{"dsn"} =~ /^DBI:Pg/) {
152 0           $dbh = DBI->connect_cached($self->{"dsn"}, $self->{"user"}, $self->{"password"}, {
153             pg_server_prepare => 0,
154             });
155             }
156             else {
157 0           $dbh = DBI->connect_cached($self->{"dsn"}, $self->{"user"}, $self->{"password"});
158             }
159 0 0         croak "Unable to establish a database connection: $DBI::errstr" unless $dbh;
160              
161             # Debug
162 0 0         print STDERR "SimpleQuery: $query\n" if $debug;
163            
164             # Prepare and execute the query
165 0           my $sth = $dbh->prepare($query);
166 0           my $rv = $sth->execute();
167            
168             # Was the query successful?
169 0 0         croak "Query error: " . $sth->errstr unless $rv;
170            
171             # Store the results
172 0 0         my $object = new DBIx::SimpleQuery::Object {
    0          
173             "count" => ($rv eq "0E0" ? 0 : $rv),
174             "results" => ($sth->{"Active"} ? $sth->fetchall_arrayref({}) : []),
175             "iter" => 0,
176             "field_count" => $sth->{"NUM_OF_FIELDS"}
177             };
178              
179             # Account for DBDs that don't set $rv to be the number of rows
180             # returned.
181 0 0 0       if (not $object->{"count"} and scalar @{$object->{"results"}}) {
  0            
182 0           $object->{"count"} = scalar @{$object->{"results"}};
  0            
183             }
184            
185             # Set the implicit variable
186 0           $_ = $object;
187            
188             # List context returns different results depending on the type of
189             # query
190 0 0         if (wantarray) {
191 0           my $first_row = $object->{"results"}->[0];
192            
193             # If only one field was retrieved, return an array of the values
194 0 0         if ($object->{"field_count"} == 1) {
195 0           my @keys = keys %{$first_row};
  0            
196 0           my $key = shift(@keys);
197 0           return map { $_->{$key} } @{$object->{"results"}};
  0            
  0            
198             }
199            
200             # Otherwise return an array of hashes containing the rows
201 0           return @{$object->{"results"}};
  0            
202             }
203              
204             # If there's only one row, and one field in that row, return the
205             # value instead of a SimpleQuery object.
206 0 0 0       if ($object->{"count"} and $object->{"count"} == 1 and
      0        
      0        
207             $object->{"field_count"} and $object->{"field_count"} == 1) {
208 0           my ($value) = values %{$object->{"results"}->[0]};
  0            
209 0           return $value;
210             }
211            
212             # In scalar or void context, return the object itself for further
213             # interaction
214 0           return $object;
215             }
216              
217             # This can be called either as a class method or a function
218             sub qs {
219 0     0 1   my $text;
220             my $self;
221              
222             # It's possible to call this function without any arguments, in
223             # which case it uses $_.
224 0 0         if (scalar @_ == 0) {
225 0           $self = new DBIx::SimpleQuery;
226 0           $text = $_;
227             }
228             else {
229 0           $self = shift();
230 0 0         if (ref($self) eq "DBIx::SimpleQuery") {
231 0           $text = shift();
232             }
233             else {
234 0           $text = $self;
235 0           $self = new DBIx::SimpleQuery;
236             }
237             }
238            
239 0 0         return "NULL" unless defined $text;
240            
241             # Establish the connection
242 0           my $dbh = DBI->connect_cached($self->{"dsn"}, $self->{"user"}, $self->{"password"});
243            
244             # If connection successfully established, use the driver's quote
245             # method for best results.
246 0 0         if ($dbh) {
247 0           return $dbh->quote($text);
248             }
249            
250             # Replace quotes with double-quotes
251 0           $text =~ s/\'/\'\'/g;
252            
253             # Returned the escaped text within quotes
254 0           return "'$text'";
255             }
256              
257             1;
258              
259             __END__