Ruby + DBI + MySQL: undefined method `to_ary' for nil:NilClass (NoMethodError) - mysql

I am trying to connect to MySQL suing DBI. I am following Using the Ruby DBI Module documentation.
Here is my code:
require 'dbi'
begin
dbh = DBI.connect("DBI:Mysql:<db_name>:<mysql_hostname>", "<mysql_user>", "<mysql_password>")
row = dbh.select_one("SELECT VERSION()")
puts "Server version: " + row[0]
rescue DBI::DatabaseError => e
puts "Something went wrong connecting the database"
puts e.errstr
end
sth = dbh.prepare("SHOW TABLES")
sth.execute
while row = sth.fetch
puts row
end
sth.finish
dbh.disconnect
This code fails with below error:
Server version: 5.6.13-log
/home/user/dbi_testing.rb:14:in `puts': undefined method `to_ary' for nil:NilClass (NoMethodError)
In above error, I am printing the MySQL version (Server version: 5.6.13-log) just to ensure that I have good working connection to the DB.
This error is thrown by the while loop above. So I changed it to below:
sth.fetch do |row|
puts row
end
And still get the exact same error.
So it means either sth.fetch method does not exists or something is wrong with the way I am accessing it.
Could you help me resolving this error.
UPDATE: I made some progress, if I put it as below, the I can see the tables:
sth.fetch_hash do |row|
puts row
end
The output is:
Server version: 5.6.13-log
{"Tables_in_mstrmd"=>"DSSCSADDRESS"}
{"Tables_in_mstrmd"=>"DSSCSBADGETB"}
{"Tables_in_mstrmd"=>"DSSCSCONTACT"}
{"Tables_in_mstrmd"=>"DSSCSDEVCKEY"}
{"Tables_in_mstrmd"=>"DSSCSPSNLZTN"}
{"Tables_in_mstrmd"=>"DSSCSRCOLCON"}
{"Tables_in_mstrmd"=>"DSSCSRINSTRG"}
{"Tables_in_mstrmd"=>"DSSCSSUBINST"}
{"Tables_in_mstrmd"=>"DSSCSSYSPROP"}
{"Tables_in_mstrmd"=>"DSSMDJRNINFO"}
{"Tables_in_mstrmd"=>"DSSMDJRNLNKS"}
{"Tables_in_mstrmd"=>"DSSMDJRNOBJC"}
{"Tables_in_mstrmd"=>"DSSMDJRNOBJD"}
{"Tables_in_mstrmd"=>"DSSMDJRNOBJS"}
{"Tables_in_mstrmd"=>"DSSMDLNKITEM"}
{"Tables_in_mstrmd"=>"DSSMDLNKPROP"}
{"Tables_in_mstrmd"=>"DSSMDOBJBLOB"}
{"Tables_in_mstrmd"=>"DSSMDOBJCMNT"}
{"Tables_in_mstrmd"=>"DSSMDOBJDEF2"}
{"Tables_in_mstrmd"=>"DSSMDOBJDEFN"}
{"Tables_in_mstrmd"=>"DSSMDOBJDEPN"}
{"Tables_in_mstrmd"=>"DSSMDOBJINFO"}
{"Tables_in_mstrmd"=>"DSSMDOBJLOCK"}
{"Tables_in_mstrmd"=>"DSSMDOBJPROP"}
{"Tables_in_mstrmd"=>"DSSMDOBJSECU"}
{"Tables_in_mstrmd"=>"DSSMDOBJTRNS"}
{"Tables_in_mstrmd"=>"DSSMDSYSPROP"}
{"Tables_in_mstrmd"=>"DSSMDUSRACCT"}
So, I am able to see the tables when I use sth.fetch_hash. Then what is wrong with sth.fetch?
Any pointers would be of immense help.
UPDATE (WORKAROUND):
I ran puts sth.methods.sort and here is the output:
fetch
fetch_all
fetch_array
fetch_hash
fetch_many
fetch_scroll
fetchable?
I changed sth.fetch to sth.fetch_array and now I am able to see the tables Fine.
The credit goes to a this comment by #philant
So, in a way my question has got a workaround.
But I still want to know why the method sth.fetch did not work ? Any explanation would be really helpful.

Related

Activerecord error: Mysql2::Error: MySQL server has gone away

i've looked into previous questions which look similar to my problem, nothing seems to be related.
After doing the following query:
Runner::Models::Job.where(:id => job_id)
I get an exception, it happens once in a while:
Mysql2::Error: MySQL server has gone away: SELECT jobs.* FROM jobs WHERE jobs.id = 7507 LIMIT 1
I use puma, and in config.ru i am using:
use ActiveRecord::ConnectionAdapters::ConnectionManagement
The thing is that this error always happens in the same place, and i cant figure out why is it happening, i've checked memory, cpu, etc'.., all seem normal.
Maybe someone will have an idea.
thanks !
Write your Resque task like this:
class MyTask
def self.perform
ActiveRecord::Base.verify_active_connections!
# rest of your code
end
end
see more details here: https://github.com/resque/resque/wiki/FAQ#how-do-you-work-around-the-mysql-server-has-gone-away-error-

Mysql + django exception: "Commands out of sync; you can't run this command now"

Running django via gunicorn to RDS (AWS mysql), I'm seeing this error in my gunicorn logs:
Exception _mysql_exceptions.ProgrammingError: (2014, "Commands out of sync; you can't run this command now") in <bound method Cursor.__del__ of <MySQLdb.cursors.Cursor object at 0x690ecd0>> ignored
I can't reliably reproduce it yet, nor can I track down the underlying code that's causing it.
I am using raw cursors in some places, following this pattern:
cursor = connections['read_only'].cursor()
sql = "select username from auth_user;"
cursor.execute(sql)
rows = cursor.fetchall()
usernames = []
for row in rows:
usernames.append(row[0])
In some places I immediately reuse the cursor for another query execute() / fetchall() pattern. Sometimes I don't.
I also use raw manager queries in some place.
I'm not explicitly closing cursors, but I don't believe that I should.
Other than that: I'm not using any stored procedures, no init_command parameters, nor anything else indicated in the other answers I've seen posted here.
Any ideas or suggestions for how to debug would be appreciated.
Check out https://code.djangoproject.com/ticket/17289
you'll need to do something like:
while cursor.nextset() is not None:
if verbose:
print "rows modified %s" % cursor.rowcount

Ruby mysql gem 'reconnect' object variable

I am encountering the 'mysql has gone away' error in Ruby after a certain amount of time that the script has been running.
I want to try to tell the mysql gem to auto-reconnect when the connection is lost.
My current code looks like the following:
def self.connect()
begin
if !##dbh.nil?
self.disconnect
end
##dbh = Mysql.real_connect(##server, ##user, ##pass, ##db)
puts "[+] Connected to the " + ##db + " database with user '" + ##user + "'"
rescue Mysql::Error => e
# log error
end
end
The following guide [0] says that the mysql gem has a 'reconnect' object variable, however, I am unsure of how to use it within my code.
How do I implement this option into the code above?
Thanks in advance,
Ryan
[0] http://www.tmtm.org/en/mysql/ruby/
EDIT ---
OK. I think I have figured it out.
I need to add ##dbh.reconnect = true after the ##dbh = Mysql.real_connect(##server, ##user, ##pass, ##db) line.
Note: According to a 'nice' chapy on IRC the mysql gem may not be the best Ruby gem to use.
If you're starting on a new project, the mysql2 gem is the way to go. It's an enormous improvement over the old version.
An attempt to Ruby-ize your example is:
def connect
begin
if (#dbh)
self.disconnect
end
#dbh = Mysql.real_connect(#server, #user, #pass, #db)
puts "[+] Connected to the #{#db} database with user '#{#user}'"
rescue Mysql::Error => e
# log error
end
end
The reason for using traditional # variables is you can use attr_accessor if you design your interface properly.
It's better to use a singleton instance than to wreck around with a singleton class. For instance:
class MyApp
def self.db
#db ||= Database.new
end
class Database
# Instance methods like initialize, connect, disconnect, etc.
end
end
You can use this like:
MyApp.db.connect
The advantage of using an instance of a class instead of a class directly is you can support more than one connection at a time.

Dealing with duplicate keys in codeigniter mysql insert

What I want to do is something like this:
function registerUser($username, $password){
$this->db->insert('tblUsers', array('username'=>$username, 'password'=>md5($password)));
if($this->db->_error_number()==1062){
return "DUPLICATE";
}
return true;
}
However, at the moment if there is a duplicate key then its not letting me get to the _error_number() bit. Its displaying an error like this:
How do I stop codeigniter from bailing with an error and passing the error number to me to deal with appropriately?
Thanks
You can access MySQL error messages in Codeigniter using:
$this->db->_error_message();
Apparently DB_DEBUG needs to be set to false in the database config file:
Ensure DB_DEBUG is set to FALSE in the database config file, or
execution will halt when a mysql error occurs (it does not get thrown,
it justs exits from the php interpreter)
Link: http://codeigniter.com/forums/viewthread/79950/#413830
Suggestion:
$orig_db_debug = $this->db->db_debug;
$this->db->db_debug = FALSE;
RUN QUERY HERE
$this->db->db_debug = $orig_db_debug;

fetching multiple result sets from mysql stored procedure in rails

I've been searching all over for tips on this and have not really had any luck so far. With the mysql2 gem, trying to execute a stored procedure that returns multiple result sets gives me an unable to return results in this context error. I found someone had suggested to use the mysql gem instead (which I can't find an explanation of what's different between the two and what I might encounter by switching), and with that I've had more progress.
Here's what I have so far:
>> db = ActiveRecord::Base.connection.raw_connection
=> #<Mysql:0x1056ae3d8>
>> ActiveRecord::Base.connection.select_all("CALL p_rpt_test('', '');")
=> [{"Header"=>"Client,Project,Type,Due Date,Assigned To"}]
>> db.more_results?
=> true
>> db.next_result
Mysql::Error: Commands out of sync; you can't run this command now
from (irb):3:in `next_result'
from (irb):3
Does anyone know of a way to get this to work, with mysql2 or mysql gems? The app is running rails 3.0.1.
Ok well I have no figured out how to get AR to do this so I've ended up just going low level and using the mysql driver itself, which mostly works...
data = Array.new
db = ActiveRecord::Base.connection.raw_connection
header = db.query("CALL #{self.proc}(#{args});")
header.each {|r| data << r}
if db.next_result
rows = db.store_result
rows.each {|r| data << r}
end
ActiveRecord::Base.connection.reconnect!
It works, but I can't imagine there's not a better way. Also I have to reconnect after this or I get an error on the next query, and I haven't found a way to properly close the session. Oh and I have to use the mysql gem and not mysql2.
Grrrrr.
We can use header.to_hash to get an array of hash, or header.rows to get an array of array.
Follow this http://api.rubyonrails.org/classes/ActiveRecord/Result.html