File Coverage

blib/lib/JDBC.pm
Criterion Covered Total %
statement 7 9 77.7
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 10 12 83.3


line stmt bran cond sub pod time code
1             package JDBC;
2              
3 5     5   153758 use warnings;
  5         32  
  5         263  
4 5     5   32 use strict;
  5         19  
  5         593  
5              
6             =head1 NAME
7              
8             JDBC - Perl 5 interface to Java JDBC (via Inline::Java)
9              
10             =head1 VERSION
11              
12             Version 0.02
13              
14             =cut
15              
16             our $VERSION = '0.02';
17              
18             =head1 SYNOPSIS
19              
20             use JDBC;
21              
22             JDBC->load_driver("org.apache.derby.jdbc.EmbeddedDriver");
23              
24             my $con = JDBC->getConnection($url, "test", "test");
25              
26             my $s = $con->createStatement();
27              
28             $s->executeUpdate("create table foo (foo int, bar varchar(200), primary key (foo))");
29             $s->executeUpdate("insert into foo (foo, bar) values (42,'notthis')");
30             $s->executeUpdate("insert into foo (foo, bar) values (43,'notthat')");
31              
32             my $rs = $s->executeQuery("select foo, bar from foo");
33             while ($rs->next) {
34             my $foo = $rs->getInt(1);
35             my $bar = $rs->getString(2);
36             print "row: foo=$foo, bar=$bar\n";
37             }
38              
39             =head1 DESCRIPTION
40              
41             This JDBC module provides an interface to the Java C and
42             C JDBC APIs.
43              
44             =cut
45              
46             our @ISA = qw(Exporter java::sql::DriverManager);
47              
48             { # the Inline package needs to be use'd in main in order to
49             # get the studied classes to be rooted in main
50             package main;
51 5     5   12509 use Inline ( Java => q{ }, AUTOSTUDY => 1 );
  0            
  0            
52             }
53              
54             use Inline::Java qw(cast caught study_classes);
55              
56             our @EXPORT_OK = qw(cast caught study_classes);
57              
58             our $debug = $ENV{PERL_JDBC_DEBUG} || 0;
59              
60             #java.sql.ParameterMetaData
61             my @classes = (qw(
62             java.sql.Array
63             java.sql.BatchUpdateException
64             java.sql.Blob
65             java.sql.CallableStatement
66             java.sql.Clob
67             java.sql.Connection
68             java.sql.DataTruncation
69             java.sql.DatabaseMetaData
70             java.sql.Date
71             java.sql.Driver
72             java.sql.DriverManager
73             java.sql.DriverPropertyInfo
74             java.sql.PreparedStatement
75             java.sql.Ref
76             java.sql.ResultSet
77             java.sql.ResultSetMetaData
78             java.sql.SQLData
79             java.sql.SQLException
80             java.sql.SQLInput
81             java.sql.SQLOutput
82             java.sql.SQLPermission
83             java.sql.SQLWarning
84             java.sql.Savepoint
85             java.sql.Statement
86             java.sql.Struct
87             java.sql.Time
88             java.sql.Timestamp
89             java.sql.Types
90             javax.sql.ConnectionEvent
91             javax.sql.ConnectionEventListener
92             javax.sql.ConnectionPoolDataSource
93             javax.sql.DataSource
94             javax.sql.PooledConnection
95             javax.sql.RowSet
96             javax.sql.RowSetEvent
97             javax.sql.RowSetInternal
98             javax.sql.RowSetListener
99             javax.sql.RowSetMetaData
100             javax.sql.RowSetReader
101             javax.sql.RowSetWriter
102             javax.sql.XAConnection
103             javax.sql.XADataSource
104             ));
105              
106             warn "studying classes\n" if $debug;
107             study_classes(\@classes, 'main');
108              
109             #Fix a long-standing bug due to changes in @ISA caching introduced in perl 5.10.0.
110             #See http://perldoc.perl.org/perl5100delta.html (search for "mro").
111             #RT 1/5/14.
112             #
113             #force a reset of the @ISA cache after injecting java.sql.DriverManager, which we inherit from:
114             @ISA = @ISA;
115              
116             # Driver => java.sql.Driver, RowSet => javax.sql.RowSet etc
117             my %class_base = map { m/^(.*\.(\w+))$/ or die; ( $2 => $1) } @classes;
118              
119             # :Driver => java::sql::Driver, :RowSet => javax::sql::RowSet etc
120             my %import_class = map {
121             (my $pkg = $class_base{$_}) =~ s/\./::/g;
122             (":$_" => $pkg)
123             } keys %class_base;
124              
125              
126             sub import {
127             my $pkg = shift;
128             my $callpkg = caller($Exporter::ExportLevel);
129              
130             # deal with :ClassName imports as a special case
131             my %done;
132             for my $symbol (@_) {
133             # is it a valid JDBC class?
134             next unless my $java_pkg = $import_class{$symbol};
135              
136             no strict 'refs';
137             # get list of "constants" which I've defined as symbols with
138             # all-uppercase names that also have defined scalar values
139             # (which also avoids perl baggage like ISA, TIEHASH, DESTROY)
140             my @const = grep {
141             /^[A-Z][_A-Z0-9]*$/ and defined ${$java_pkg.'::'.$_}
142             } keys %{ $java_pkg.'::' };
143              
144             # now export those as real perl constants
145             warn "import $symbol ($java_pkg): @const" if $debug;
146             for my $const (@const) {
147             no strict 'refs';
148             my $scalar = ${"$java_pkg\::$const"};
149             *{"$callpkg\::$const"} = sub () { $scalar };
150             }
151             ++$done{$symbol};
152             }
153             @_ = grep { !$done{$_} } @_; # remove symbols we've now dealt with
154              
155             return if !@_ and %done; # we've dealt with all there was
156             # else call standard import to handle anything else
157             local $Exporter::ExportLevel = $Exporter::ExportLevel + 1;
158             return $pkg->SUPER::import(@_);
159             }
160              
161             =head1 METHODS
162              
163             =head2 load_driver
164              
165             The load_driver() method is used to load a driver class.
166              
167             JDBC->load_driver($driver_class)
168              
169             is equivalent to the Java:
170              
171             java.lang.Class.forName(driver_class).newInstance();
172              
173             =cut
174              
175             sub load_driver {
176             my ($self, $class) = @_;
177             study_classes([$class], 'main');
178             }
179              
180             # override getDrivers to return an Enumeration (not private class)
181              
182             sub getDrivers {
183             return cast('java.util.Enumeration', shift->SUPER::getDrivers)
184             }
185              
186             =head1 FUNCTIONS
187              
188             =head2 cast
189              
190             =head2 caught
191              
192             =head2 study_classes
193              
194             The cast(), caught(), and study_classes() functions of Inline::Java are also
195             optionally exported by the JDBC module.
196              
197             =cut
198              
199             =head1 IMPORTING CONSTANTS
200              
201             Java JDBC makes use of constants defined in
202              
203             import java.sql.*;
204             ...
205             stmt = con.prepareStatement(PreparedStatement.SELECT);
206              
207             the package can also be specified with the C which then avoids the need
208             to prefix the constant with the class:
209              
210             import java.sql.PreparedStatement;
211             ...
212             stmt = con.prepareStatement(SELECT);
213              
214             In Perl the corresponding code can be either:
215              
216             use JDBC;
217             ...
218             $stmt = $con->prepareStatement($java::sql::PrepareStatement::SELECT);
219              
220             or, the rather more friendly:
221              
222             use JDBC qw(:PreparedStatement);
223             ...
224             $stmt = $con->prepareStatement(SELECT);
225              
226             When importing a JDBC class in this way the JDBC module only imports defined
227             scalars with all-uppercase names, and it turns them into perl constants so the
228             C<$> is no longer needed.
229              
230             All constants in all the java.sql and javax.sql classes can be imported in this way.
231              
232             =cut
233              
234             warn "running\n" if $debug;
235              
236             1; # End of JDBC
237              
238             __END__