File Coverage

blib/lib/DBIx/AnyDBD.pm
Criterion Covered Total %
statement 18 117 15.3
branch 0 60 0.0
condition 0 11 0.0
subroutine 6 15 40.0
pod 3 6 50.0
total 27 209 12.9


line stmt bran cond sub pod time code
1             # $Id: AnyDBD.pm,v 1.15 2002/09/04 12:05:03 matt Exp $
2              
3             package DBIx::AnyDBD;
4 1     1   5365 use DBI;
  1         25075  
  1         65  
5 1     1   11 use strict;
  1         3  
  1         106  
6 1     1   16 use vars qw/$AUTOLOAD $VERSION/;
  1         1  
  1         560  
7              
8             $VERSION = '2.01';
9              
10             sub new {
11 0     0 1   my $class = shift;
12 0           my %args = @_;
13 0   0       my $dbh = DBI->connect(
14             $args{dsn},
15             $args{user},
16             $args{pass},
17             ($args{attr} ||
18             {
19             AutoCommit => 1,
20             PrintError => 0,
21             RaiseError => 1,
22             })
23             );
24 0 0         die "Can't connect: " . DBI->errstr unless $dbh;
25 0   0       my $package = $args{'package'} || $class;
26 0           my $self = bless { 'package' => $package, dbh => $dbh }, $class;
27 0           $self->rebless;
28 0 0         $self->_init if $self->can('_init');
29 0           return $self;
30             }
31              
32             sub connect {
33 0     0 1   my $class = shift;
34 0           my ($dsn, $user, $pass, $args, $package) = @_;
35 0           my $dbh = DBI->connect($dsn, $user, $pass, $args);
36 0 0         return undef unless $dbh;
37 0   0       $package ||= $class;
38 0           my $self = bless { 'package' => $package, 'dbh' => $dbh }, $class;
39 0           $self->rebless;
40 0 0         $self->_init if $self->can('_init');
41 0           return $self;
42             }
43              
44             sub rebless {
45 0     0 0   my $self = shift;
46 0           my $driver = ucfirst($self->{dbh}->{Driver}->{Name});
47 0 0         if ( $driver eq 'Proxy' ) {
48             # Looking into the internals of DBD::Proxy is maybe a little questionable
49 0           ($driver) = $self->{dbh}->{proxy_client}->{application} =~ /^DBI:(.+?):/;
50             }
51 0           my $class = $self->{'package'};
52 0           my ($odbc, $ado) = ($driver eq 'ODBC', $driver eq 'ADO');
53 0 0 0       if ($odbc || $ado) {
54 0           my $name;
55            
56 0 0         if ($odbc) {
    0          
57 1     1   7 no strict;
  1         1  
  1         953  
58 0           $name = $self->{dbh}->func(17, GetInfo);
59             }
60             elsif ($ado) {
61 0           $name = $self->{dbh}->{ado_conn}->Properties->Item('DBMS Name')->Value;
62             }
63             else {
64 0           die "Can't determine driver name!\n";
65             }
66            
67 0 0         if ($name eq 'Microsoft SQL Server') {
    0          
    0          
    0          
    0          
68 0           $driver = 'MSSQL';
69             }
70             elsif ($name eq 'SQL Server') {
71 0           $driver = 'Sybase';
72             }
73             elsif ($name =~ /Oracle/) {
74 0           $driver = 'Oracle';
75             }
76             # elsif ($name eq 'ACCESS') {
77             # $driver = 'Access';
78             # }
79             # elsif ($name eq 'Informix') {
80             # $driver = 'Informix'; # caught by "else" condition below
81             # }
82             elsif ($name eq 'Adaptive Server Anywhere') {
83 0           $driver = 'ASAny';
84             } elsif ($name eq 'ADABAS D') {
85 0           $driver = 'AdabasD';
86             }
87             else { # this should catch Access and Informix
88 0           $driver = lc($name);
89 0           $driver =~ s/\b(\w)/uc($1)/eg;
  0            
90 0           $driver =~ s/\s+/_/g;
91             }
92             }
93            
94 0           my $dir;
95 0           ($dir = $self->{package}) =~ s/::/\//g;
96 0 0         load_module("$dir/Default.pm") or die "Cannot find $dir/Default.pm module in \@INC for $self->{package}!";
97              
98 0 0         if (!load_module("$dir/$driver.pm")) {
99             # no package for driver - use Default instead
100 0           bless $self, "${class}::Default";
101             # make Default -> DBIx::AnyDBD hierarchy
102 0           add_isa("${class}::Default", 'DBIx::AnyDBD');
103             }
104             else {
105             # package OK...
106            
107 0           bless $self, "${class}::${driver}";
108            
109 0 0         if ($ado) {
110 0 0         if (load_module("$dir/ADO.pm")) {
111 0 0         if (!load_module("$dir/ODBC.pm")) {
112 0           add_isa("${class}::${driver}", "${class}::ADO");
113 0           add_isa("${class}::ADO", "${class}::Default");
114             }
115             else {
116 0           add_isa("${class}::${driver}", "${class}::ADO");
117 0           add_isa("${class}::ADO", "${class}::ODBC");
118 0           add_isa("${class}::ODBC", "${class}::Default");
119             }
120 0           return;
121             }
122             }
123            
124 0 0         if ($odbc) {
125 0 0         if (load_module("$dir/ODBC.pm")) {
126 0           add_isa("${class}::${driver}", "${class}::ODBC");
127 0           add_isa("${class}::ODBC", "${class}::Default");
128 0           return;
129             }
130             }
131            
132             # make Default -> DBIx::AnyDBD hierarchy
133 0           add_isa("${class}::Default", 'DBIx::AnyDBD');
134            
135             # make Driver -> Default hierarchy
136 0           add_isa("${class}::${driver}", "${class}::Default");
137             }
138            
139             }
140              
141             sub add_isa {
142 0     0 0   my ($class, $newval) = @_;
143 1     1   7 no strict 'refs';
  1         2  
  1         248  
144 0 0         unshift @{"${class}::ISA"}, $newval unless $class->isa($newval);
  0            
145             }
146              
147             sub load_module {
148 0     0 0   my $module = shift;
149            
150 0           eval {
151 0           require $module;
152             };
153 0 0         if ($@) {
154 0 0         if ($@ =~ /^Can't locate $module in \@INC/) {
155 0           undef $@;
156 0           return 0;
157             }
158             else {
159 0           die $@;
160             }
161             }
162            
163 0           return 1;
164             }
165              
166             sub get_dbh {
167             # maybe add code here to check connection status.
168             # or maybe add check once every 10 get_dbh's...
169 0     0 1   return shift->{dbh};
170             }
171              
172             sub DESTROY {
173 0     0     my $self = shift;
174 0           my $dbh;
175 0 0         if ($dbh = $self->get_dbh) {
176 0           $dbh->disconnect;
177             }
178             }
179              
180             sub AUTOLOAD {
181 0     0     (my $func = $AUTOLOAD) =~ s/.*:://;
182 1     1   6 no strict 'refs';
  1         1  
  1         385  
183             # The following is much more elegant but doesn't work!
184             # *$func = sub {
185             # unshift @_ => shift->get_dbh;
186             # goto &{$_[0]->can($func)};
187             # };
188             *$func = sub {
189 0     0     my $dbh = shift->get_dbh;
190 0 0         if (wantarray) {
    0          
191 0           my @r = eval { $dbh->$func(@_) };
  0            
192 0 0         return @r unless $@;
193             } elsif (defined wantarray) {
194 0           my $r = eval { $dbh->$func(@_) };
  0            
195 0 0         return $r unless $@;
196             } else {
197 0           eval { $dbh->$func(@_) };
  0            
198 0 0         return unless $@;
199             };
200 0 0         if ( $@ =~ /(.*) at ${\__FILE__} .*$/ ) {
  0            
201             # We want croak() to report errors as occouring
202             # in the implementation class even though we are related
203             package DBIx::AnyDBD::Carp;
204 0           require Carp;
205 0           Carp::croak "$1";
206             }
207 0           die; # Unreachable ?
208 0           };
209 0           goto &$func;
210             }
211              
212             1;
213              
214             __END__