Ruby-DBI and JDBC


Last week I decided it was time to get Ruby-DBI working with JDBC. I resolved to get on it since it would be highly useful and probably not so hard either. But as it turned out I didn’t really need to do anything. The work has already been done by Kristopher Schmidt. Very nice. So instead, this post will detail how to get it working with JRuby.

First download the Ruby-DBI distribution from RubyForge. Secondly, unpack. The third step is to configure and install it. Execute these commands inside the Ruby-DBI directory:

jruby setup.rb config --without=dbd_sqlite,dbd_sybase
jruby setup.rb setup
jruby setup.rb install

Now you should have Ruby-DBI installed, but no DBD drivers. Verify that it’s actually installed by running “jirb -rdbi”. The next step is to install the JDBC driver. First create a directory called $JRUBY_HOME/lib/ruby/site_ruby/1.8/DBD/Jdbc. Download Jdbc.rb and JdbcTypeConversions.rb and put them into this directory. Also make sure that the JDBC driver you want to use is on your CLASSPATH. Now you can create a script like this:

require 'dbi'

DBI.connect('DBI:Jdbc:mysql://localhost/test', 'test', 'test',
'driver'=>'com.mysql.jdbc.Driver') do |dbh|
p dbh.select_all('SELECT * FROM a_table')
end

Make sure that you include the name of the driver as done in this code. The first parameter should be the regular JDBC URI with DBI: first. In this case it’s the test database on localhost I connecting to, using the test username and test password. More information about how Ruby-DBI can be used can be found by Google.


9 Comments, Comment or Ping

  1. Admin

    Have anybody tried this on Windows platform.

    I have instaled jRuby 1.0.1 and DBI 0.1.1 and wasn’t able to install DBI.

    I got an error stating that: “config: unknown option –without …”

    the very same command have executed perfectly in Ruby. If I omit the without option, than setup command fails.

    I would like to use jRuby-DBI-jdbc very much. Specially for accesing legacy data.

    October 3rd, 2007

  2. Stuart Holden

    Try quoting the final argument…

    jruby setup.rb config “–without=dbd_sqlite,dbd_sybase”

    It works for me when I do this.

    Stu

    October 4th, 2007

  3. Admin

    Thanks. Works like magic. Thanks again.

    October 8th, 2007

  4. Adam Boyle

    First I must say that this tutorial saved me a lot of grief in exporting data from a Cache’ database… my sincerest thanks for that!

    Unfortunately there seems to be a slight problem in the JDBC.rb file in the way that nulls are handled for numeric columns… they are returned as zero. This is due to the fact that Java primitive types cannot be null.

    In the get_value(columnNumber, rs, metaData) function for the Statement class, the value of numeric fields is returned via ResultSet.getLong()… which returns a Java primitive long, and as such is afflicted by the null -> 0 problem. Is there an easy way to fix this code so that null values in a numeric column are returned as null and not zero? Maybe by applying a wrapper?

    Any help you can provide is most appreciated.

    December 20th, 2007

  5. Briefcase S

    It turns out I was able to solve my own problem with a few simple modifications to JDBC.rb.

    The new definition for get_value() in the Statement class is as follows (Ola: you should consider allowing <code> tags…:):

    def get_value(columnNumber, rs, metaData)
    return case metaData.getColumnType(columnNumber)
    when java.sql.Types::BIT
    unless rs.getObject(columnNumber).nil?
    rs.getBoolean(columnNumber)
    else
    rs.getObject(columnNumber)
    end

    when java.sql.Types::NUMERIC, java.sql.Types::DECIMAL
    unless rs.getObject(columnNumber).nil?
    metaData.getScale(columnNumber) == 0 ? rs.getLong(columnNumber) : rs.getDouble(columnNumber)
    else
    rs.getObject(columnNumber)
    end

    when java.sql.Types::DATE
    jdbcdate_to_dbidate( rs.getDate(columnNumber))
    when java.sql.Types::TIME
    jdbctime_to_dbitime( rs.getTime(columnNumber))
    when java.sql.Types::TIMESTAMP
    jdbctimestamp_to_dbitimestamp( rs.getTimestamp(columnNumber))
    else
    rs.getObject(columnNumber)
    end
    end

    December 21st, 2007

  6. Briefcase S

    Also, there is a small defect in JdbcTypeConversions.rb that has been pointed out back at RubyForge…

    The following code:

    def jdbc_to_dbi_sqltype(jdbctype)
    return case jdbctype
    when Types::BIGINT then DBI::BIGINT

    should be:

    def jdbc_to_dbi_sqltype(jdbctype)
    return case jdbctype
    when Types::BIGINT then DBI::SQL_BIGINT

    Just thought you’d like to know!

    December 21st, 2007

  7. Brad

    Thanks, this has been very useful.

    Unfortunately, this doesn’t work with the new version of DBI (0.4.0) straight out of the box because of some API changes. I’ve been playing around a little with it, and I haven’t been successful. Maybe someone can get it working?

    September 15th, 2008

  8. Chad Johnson

    Ola released this code as a gem. Gem install with :

    jruby -S gem install dbd-jdbc

    And, yes, it is now updated to work with DBI 0.4.0

    October 21st, 2008

  9. erikh

    I know this is extremely late, but it makes me so happy to see this kind of progress with this project, it’s nice to feel that the project is finally starting to see some visibility.

    -Erik

    December 31st, 2008

Reply to “Ruby-DBI and JDBC”