Wonderfully helpful reply Jason. Many thanks.

I wrote JDBC as an experiment. I don't have time to maintain it myself,
sadly, but I'd be very happy for others to either contribute or take
over the module.

Tim.

On Tue, Sep 29, 2009 at 01:52:25PM -0400, Jason Stelzer wrote:
> I never heard of the JDBC module before now, but having looked at the
> code, it makes a couple of naive assumptions.  Fortunately they're
> pretty easily fixed and not a big deal. To be clear, given how new
> JDBC is, it doesn't shock me that there are a couple minor bugs around
> some drivers.
> 
> At its core, the problem is type casting. Oracle's drivers are....
> annoying to deal with here. The problem you're experiencing is due to
> the fact that you're getting back the wrong interface types from the
> driver. Without patching JDBC.pm you can get the script below to work
> like this:
> 
> #!/usr/bin/perl
> use JDBC;
> use Inline::Java qw(cast);
> use strict;
> JDBC->load_driver("oracle.jdbc.driver.OracleDriver");
> my $url = "jdbc:oracle:thin:system/passwo...@localhost:1521:xe";
> my $con = cast('java.sql.Connection',JDBC->getConnection($url));
> my $sql = "SELECT TABLE_NAME FROM USER_TABLES";
> my $ps  = $con->prepareStatement($sql);
> my $rs = cast('java.sql.ResultSet',$ps->executeQuery());
> # Fake out a row num, select it if you really care about it.
> my $foo = 0;
> while ($rs->next) {
>  my $bar = $rs->getString(1);
>  print "row: foo=$foo, bar=$bar\n";
>  $foo++;
> }
> 
> 
> One of the problems that the JDBC module is going to face is that
> there are a lot of buggy JDBC drivers out there that do similar things
> as to what is going on here with oracle. One strategy would be to
> create some perl facade objects to wrap the java objects and enforce
> the api by wrapping the calls to the internal java object and cast
> under the hood. I've done some tricks with autoloader so that I've
> only had to wrap methods that need wrapped.
> 
> For instance, if one were to take the JDBC java api and hash method
> names to expected return types, you could put a jdbc object within a
> perl object. $obj = PACKAGE->new($java_ref);
> 
> Then, take the $method => returnType above and handle it via
> AUTOLOAD.... something like
> 
> sub AUTOLOAD {
>     my $self = shift;
>     return if $AUTOLOAD =~ /::DESTROY$/;
>     my ($meth) = $AUTOLOAD =~ /::(\w+)$/;
>     $meth = "SUPER::$meth";
>     return $self->castByInternalMap($self->$meth);
> }
> 
> Obviously this solution isn't perfect as it doesn't handle arguments,
> but that is trivial. What I'm getting at is, in order for JDBC.pm to
> really shine, it's going to need to do a little more work to enforce
> the rules of the API, but that work isn't that far of a reach. As
> we've seen, there are vendors out there that rely on some magic in
> order to work.
> 
> If you were to go that far, it'd be a pretty cool trick to wrap some
> tied arrays and hashes around some things (like result sets) and fake
> out the (old) DBI interface. I did some stuff like this with ejbs. Its
> very convenient to be able to do things in perl like:
> 
> my $ar = $ejb->getBigListOfStuff();
> foreach my $rec (@$ar){
> .....
> }
> 
> And let the tied array handle the whole calling next, getting an iterator, 
> etc.
> 
> Anyways, I hope that helps.
> 
> 
> On Tue, Sep 29, 2009 at 12:44 PM,  <j...@joedog.org> wrote:
> > Hi. I posted this question to the author of JDBC and he proposed that I
> > post it here.
> >
> > I'm trying to execute the following code:
> >
> > #!/usr/bin/perl
> > use JDBC;
> > use strict;
> > JDBC->load_driver("oracle.jdbc.driver.OracleDriver");
> > my $url = "jdbc:oracle:thin:haha/pa...@server.haha.com:1521:lsd1";
> > my $con = JDBC->getConnection($url);
> > my $sql = "SELECT TABLE_NAME FROM USER_TABLES";
> > my $ps  = $con->prepareStatement($sql);
> > my $rs  = $con->executeQuery();
> >
> > while ($rs->next) {
> >  my $foo = $rs->getInt(1);
> >  my $bar = $rs->getString(2);
> >  print "row: foo=$foo, bar=$bar\n";
> > }
> >
> > And I get the following error:
> >
> > lsnas003 # perl ./haha
> > You are not allowed to invoke method prepareStatement in class
> > oracle.jdbc.driver.T4CConnection: Class InlineJavaUserClassLink can not
> > access a member of class oracle.jdbc.driver.PhysicalConnection with
> > modifiers "public synchronized" at (eval 56) line 927
> >  at ./haha line 12
> >
> > Any thoughts?
> >
> > TIA,
> > Jeff
> >
> >
> >
> >

Reply via email to