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__ |