JRuby and SQLite3 - jdbc

I'm trying to make work JRuby and SQLite3 with the following gems:
bouncy-castle-java (1.5.0146.1)
bundler (1.3.2)
dbd-jdbc (0.1.6 java)
dbi (0.4.5)
deprecated (2.0.1)
jdbc-sqlite3 (3.7.2.1)
jruby-launcher (1.0.15 java)
jruby-openssl (0.8.2)
json (1.7.7 java)
rack (1.5.2)
rack-protection (1.4.0)
rake (10.0.3)
rubygems-bundler (1.1.1)
rvm (1.11.3.6)
sinatra (1.3.5)
sqlite3 (1.3.7)
tilt (1.3.5)
and this code:
require 'java'
require 'dbi'
require 'dbd/Jdbc'
require 'jdbc/sqlite3'
dbh = DBI.connect(
"DBI:jdbc:sqlite:db.sqlite", # connection string
'', # no username for sqlite3
'', # no password for sqlite3
'driver' => 'org.sqlite.JDBC') # need to set the driver
But I have this error:
DBI::InterfaceError: Unable to load driver 'jdbc' (underlying error: wrong constant name jdbc)
load_driver at /home/gl/.rvm/gems/jruby-1.7.3/gems/dbi-0.4.5/lib/dbi.rb:300
mon_synchronize at /home/gl/.rvm/rubies/jruby-1.7.3/lib/ruby/1.9/monitor.rb:211
load_driver at /home/gl/.rvm/gems/jruby-1.7.3/gems/dbi-0.4.5/lib/dbi.rb:242
_get_full_driver at /home/gl/.rvm/gems/jruby-1.7.3/gems/dbi-0.4.5/lib/dbi.rb:160
connect at /home/gl/.rvm/gems/jruby-1.7.3/gems/dbi-0.4.5/lib/dbi.rb:145
(root) at srv.rb:6
Have you got an idea?

I've just been trying to work this out myself, and eventually succeeded - the problem is that the driver name is now 'Jdbc', rather than 'jdbc' - capitalization is important, both in the connection string, and the require statement. If you change your connection string to "DBI:Jdbc:sqlite:db.sqlite" it should work fine.

I suggest you use ActiveRecord rather than DBI.
You can execute bare SQL thus:
ActiveRecord::Base.connection.execute("SELECT * FROM some_table")

The accepted answer does not work (for me at least). I searched SO and the Web for hours (there's a lot of good and bad information out there) and finally came upon a solution that works (for me at least). A large part of the problem is solved by adding the line 'Jdbc::SQLite3.load_driver'.
require 'java'
require 'jdbc/sqlite3'
module JavaSql
include_package 'java.sql'
end
Jdbc::SQLite3.load_driver
Java::org.sqlite.JDBC
conn_str = 'jdbc:sqlite:../Data/AflBettingHistory.db3'
conn = JavaSql::DriverManager.getConnection(conn_str)
stm = conn.createStatement
rs = stm.executeQuery("select Name from Team")
while (rs.next) do
puts rs.getString("Name")
end
rs.close
stm.close
conn.close

Related

Ruby/Mongo: Why am I receiving uninitialized constant MongoClient error?

I am following this tutorial but I've hit a problem. I keep getting the error:
server.rb:10:in `<main>': uninitialized constant Mongo::MongoClient (NameError)
I am using the following gems:
Using bson 4.1.1
Using bson_ext 1.5.1
Using daemons 1.2.3
Using eventmachine 1.2.0.1
Using rack 1.6.4
Using tilt 2.0.5
Using bundler 1.12.5
Using mongo 2.2.5
Using rack-protection 1.5.3
Using thin 1.7.0
Using sinatra 1.4.7
My code:
require 'rubygems'
require 'bundler/setup'
require 'sinatra'
require 'json'
require 'mongo'
include Mongo
mongo_client = MongoClient.new("localhost", 27017)
I've required the mongo gem and included the Mongo class. Why isn't MongoClient being recognised? Why am I receiving the error?
Because MongoClient doesn't exist in that version of the mongo driver. As of the 2.0 version of the driver, the client class is Mongo::Client.
The 2.0 version introduced a number of big changes to the api, so I wouldn't recommend following a tutorial written for earlier versions - it looks like that page was last updated in Feb 2014. The mongodb docs have an up to date tutorial but for some reason the old tutorial is top of the google results.

requiring old versions of gems

Since none of the tools I have handy on my Windows laptop can export decent CSV files from SQL Server to save their lives, I figured I'd roll my own in a few lines of Ruby.
Because I'm hitting the version of SQL Server from the turn of the century, I have to use an old version of activerecord-sqlserver-adapter. As far as I can tell I'm doing this correctly, and should be using activerecord ~> 2.2.3 and the 2-3-stable branch of activerecord-sqlserver-adapter, but I am getting an error that complains it is Unable to activate activerecord-sqlserver-adapter-3.2.12, because activerecord-2.2.3 conflicts with activerecord (~> 3.2.0). Here's my code (without anything specifically related to CSVs):
#!/usr/bin/env ruby
gem 'activerecord', "~> 2.2.3"
gem 'activerecord-sqlserver-adapter', github: 'arthrex/activerecord-sqlserver-adapter', :branch => '2-3-stable'
require 'activerecord'
require 'activerecord-sqlserver-adapter'
require 'pry'
ActiveRecord::Base.establish_connection(
:adapter => "sqlserver",
:mode => "odbc",
:username => "c3",
:password => "92641",
:dsn => "Connect3"
)
ActiveRecord::Base.table_name_prefix = 'dbo.'
class Dwnld_Hdr < ActiveRecord::Base
end
pry
Why is it trying to load activerecord (~> 3.2.0) in the first place?
I think in this case you might probably use bundler, because then it will allow you to run the specific gem sets.
Read here and here to get an idea on how to use bundler in a non-Rails project.

DBI + ruby-odbc fails with Bundler involved

I'm connecting to Exasol using the dbi and ruby-odbc gems with unixodbc and it works fine, loaded like this:
require 'dbi'
require 'odbc_utf8'
When I add Bundler to the mix, ruby-odbc doesn't seem to be able to find the odbc configuration:
Could not load driver (undefined method `driver_name' for ODBC:Module)
/usr/lib/ruby/gems/1.9.1/gems/dbi-0.4.5/lib/dbi.rb:318:in `rescue in load_driver'
/usr/lib/ruby/gems/1.9.1/gems/dbi-0.4.5/lib/dbi.rb:242:in `load_driver'
/usr/lib/ruby/gems/1.9.1/gems/dbi-0.4.5/lib/dbi.rb:160:in `_get_full_driver'
/usr/lib/ruby/gems/1.9.1/gems/dbi-0.4.5/lib/dbi.rb:145:in `connect'
It doesn't matter if I require it via Bundler.require (with gem 'ruby-odbc', require: 'odbc_utf8' in the Gemfile) or with require 'bundler/setup' and require 'odbc_utf8'.
This is how I try to connect:
DBI.connect('DBI:ODBC:exa', config['username'], config['password'])
In case it matters, this is what my .odbc.ini looks like:
[exa]
Driver = /opt/EXASolution_ODBC-4.0.8/lib32/libexaodbc-uo22.so
EXAHOST = 192.168.235.84..86:8563
edit: The way it works without Bundler only does so with Ruby 1.9.3. It looks to me like a scoping issue, as driver_name is a variable passed as an argument to the method that raises the exception.
Please try to install: gem install dbd-odbc

Twitter entities no longer recognized in ruby script

I have a ruby script that scans each type of entity in a given tweet:
status = Twitter::Client.new.status(tweet[:id_str], {:include_entities => "1"})
status[:entities].each do |x|
#job on the entity
end
It was doing good until yesterday. Now I get NoMethodError: undefined method 'entities' for #<Twitter::Status:0x000001033e1800>
I can't figure it out since I've checked that status does include entities after the first line.
Any clues?
EDIT: turns out it's the new version of the twitter gem (v2.0.0) which is in cause. First I'd like to downgrade it to the last version working (v1.7.2), but I'm getting an annoying gem version error:
Bundler could not find compatible versions for gem "hashie":
In Gemfile:
topsy (~> 0.3.6) depends on
hashie (~> 1.0.0)
twitter (= 1.7.2) depends on
hashie (1.1.0)
How can I work it out?
If you need specific gem's version, you can forcely set it throught Gemfile:
gem "rack", "1.0.1"
gem "rails", ">=2.3.2"
In the end it was a conflict in the Gemfile:
gem 'topsy', '~> 0.3.6'
gem 'twitter', '1.7.2'
were requesting different versions of hashie, so I just deleted the version of topsy and it worked.

Why is my simple Ruby SQLite3 example failing?

In my attempt to learn Ruby, I've been reading Mr. Neighborly's Humble Little Ruby Book.
Most examples have been very easy to follow giving me a good introduction to Ruby, however I can't run DB related examples easily.
I'm trying to run this code: (slightly modified from the example given in the book)
#!/usr/bin/ruby
require 'rubygems'
require 'dbi'
DBI.connect('DBI:SQLite3:testdb', 'ruby', 'ruby') do | dbh |
dbh.do('CREATE TABLE slugs(name varchar(20), age int);') rescue puts "TABLE slugs already exists."
sql = "INSERT INTO slugs (name, age) VALUES (?, ?)"
dbh.prepare(sql) do |st|
1.upto(20) do |i|
st.execute("slug #{i}", "#{i}")
end
end
end
When run, it inserts one row in the database, then it gives me the following error:
/var/lib/gems/1.8/gems/sqlite3-ruby-1.3.2/lib/sqlite3/statement.rb:41:in `bind_param': library routine called out of sequence (SQLite3::MisuseException)
from /var/lib/gems/1.8/gems/sqlite3-ruby-1.3.2/lib/sqlite3/statement.rb:41:in `bind_params'
from /var/lib/gems/1.8/gems/sqlite3-ruby-1.3.2/lib/sqlite3/statement.rb:37:in `each'
from /var/lib/gems/1.8/gems/sqlite3-ruby-1.3.2/lib/sqlite3/statement.rb:37:in `bind_params'
from /var/lib/gems/1.8/gems/dbd-sqlite3-1.2.5/lib/dbd/sqlite3/statement.rb:71:in `bind_params'
from /var/lib/gems/1.8/gems/dbi-0.4.5/lib/dbi/handles/statement.rb:115:in `execute'
from /media/dev/ruby-prax/moi.rb:12
from /media/dev/ruby-prax/moi.rb:11:in `upto'
from /media/dev/ruby-prax/moi.rb:11
from /var/lib/gems/1.8/gems/dbi-0.4.5/lib/dbi/handles/database.rb:61:in `prepare'
from /media/dev/ruby-prax/moi.rb:10
from /var/lib/gems/1.8/gems/dbi-0.4.5/lib/dbi/handles/driver.rb:41:in `connect'
from /var/lib/gems/1.8/gems/dbi-0.4.5/lib/dbi.rb:148:in `connect'
from /media/dev/ruby-prax/moi.rb:5
TABLE slugs already exists.
I am on Ubuntu 10.04 at the moment.
Version info:
tlee#tim-ubuntu:/media/dev/ruby-prax$ ruby -v
ruby 1.8.7 (2010-01-10 patchlevel 249) [x86_64-linux]
tlee#tim-ubuntu:/media/dev/ruby-prax$ gem list
*** LOCAL GEMS ***
abstract (1.0.0)
daemons (1.1.0)
dbd-mysql (0.4.4)
dbd-odbc (0.2.5)
dbd-sqlite3 (1.2.5)
dbi (0.4.5)
deprecated (3.0.0, 2.0.1)
erubis (2.6.6)
eventmachine (0.12.10)
extlib (0.9.15)
json_pure (1.4.6)
mysql (2.8.1)
rack (1.2.1)
sqlite3-ruby (1.3.2)
thin (1.2.7)
thor (0.14.1)
tlee#tim-ubuntu:/media/dev/ruby-prax$ sqlite3 --version
3.6.22
tlee#tim-ubuntu:/media/dev/ruby-prax$
What am I doing wrong?
I experienced the same problem. There is an issue on github about the SQLite driver for DBD failing when you use a prepared INSERT statement more than once. Personally, I've taken the recommendation in the answer there of moving to RDBI, since Ruby/DBI is apparently no longer being maintained. Moving to RDBI required very minimal code changes.
Your table definition is:
slugs(name varchar(20), age int);
but you are trying to insert:
st.execute("slug #{i}", "#{i}")
Note that "#{i}" is not an integer, it's a string. Change it to i, as in this example:
st.execute("slug #{i}", i)
Then see what happens.
I somehow think that several of sqlite3 libraries on Ruby are missing reset and clear methods for the statement class.
When same SQL statement is executed repeatedly, a statement is prepared once and executed with a fresh set of values. But after the statement is executed and before it is re-bound, it needs to be reset (and often cleared). The point is that it is faster to reset a used statement than "compiling and optimizing" the same SQL over and over again. Most of you probably know all this... but here's the link to the SQLite documentation of the relevant part:
https://www.sqlite.org/c3ref/stmt.html
I don't see reset and clear methods in SQLite3::Statement class, so these might be somehow missed from this implementation, or there is some other mechanism to reset/clear automatically when reused, but that mechanism is somehow not triggered. However, it is not even mentioned in the documentation... at least I couldn't find it.
I think clear_bindings and reset methods are missing from SQLite3::Statement class.
https://github.com/sparklemotion/sqlite3-ruby/issues/158

Resources