Vanilla MySQL access from Ruby 1.9 on Snow Leopard - mysql

I am running Ruby 1.9 (ruby 1.9.1p376 (2009-12-07 revision 26041) [i386-darwin10]) on Slow Leopard (installed via MacPorts).
I then installed the Ruby MySQL client library via MacPorts:
install rb19-mysql
Trying to use it I get the following error:
db.rb:4:in `initialize': wrong number of arguments(4 for 0) (ArgumentError)
from db.rb:4:in `new'
from db.rb:4:in `'
My code:
require 'mysql'
require 'pp'
dbh = Mysql.new("localhost", "testuser", "testpass", "test")
puts "Server version: " + dbh.get_server_info
It seems like I am missing something very basic here.
Did I install the right client library?
I am using it correctly?
Am I missing some other dependencies?
Would appreciate if someone could point me in the right direction.
Thanks!

What you're looking for is:
dbh = Mysql.real_connect("localhost", "testuser", "testpass", "test")

I have never written a line of Ruby in my life so maybe I'm going to embarrass myself, but don't you have to initialize Mysql first? I'm quite sure the fact that the function expects 0 parameters means it doesn't exist yet.
In the test file of the package you mention (you got me curious), I see the following line:
assert_nothing_raised{#m = Mysql.init}
your syntax seems to be correct, however. From the same test file
assert_nothing_raised{#m = Mysql.new(#host, #user, #pass, #db, #port, #sock, #flag)}
I would assume you need to do a Mysql.init() first.
If I'm wrong, let me know and I'll remove the answer.

Your code looks solid to me; it matches the examples given on the rb19-mysql homepage very well.
my = Mysql.new(hostname, username, password, databasename)
st = my.prepare("insert into tblname (col1,col2,col3) values (?,?,?)")
st.execute("abc",123,Time.now)
st.prepare("select col1,col2,col3 from tblname")
st.execute
st.fetch # => ["abc", 123, #<Mysql::Time:2005-07-24 23:52:55>]
st.close
Which would seem to indicate that there's probably something not quite right with the port install. There were all kinds of issues with MacPorts not working properly after snow leopard upgrades - are you falling victim to this? I had to rebuild all my ports before they worked properly.
Also (and I know this is like religion to some people), you might want to consider ditching the MacPort version and just grab the MySql gem. For whatever reason, using the gems has been a far more pleasurable experience for me.
Hope that helps - good luck!

Related

Perl issues regarding mysql:Can't locate object method "connect" and Can't use string ("") as a HASH

I'm currently trying to run NERVE a vaccine development program that is made up of Perl scripts and have trouble getting it to run properly. I've downloaded and installed all prerequisites but every time I reach the mysql step of the code, it crashes, and an error message says: Can't locate object method "connect" via package "Mysql" (perhaps you forgot to load "Mysql"?) at ./NERVE line 340, line 5. I took a look at the code and changed "use mysql" to "use DBI" and "use DBD:mysql" but then I get the error: Can't use string ("") as a HASH ref while "strict refs" in use at /usr/local/lib/perl/5.14.2/DBI.pm line 604, line 5.
I would appreciate if anyone could look the code over for the mysql section and give me advice on how to fix it so I can run the program properly. I tried emailing the developers but no response so I'm hoping you guys can help me.
Below is the perl code for NERVE for the mysql section.
use mysql;
$db=Mysql->connect("$host","$database","$user","$password");
if(!$db || (!$host || !$database || !$user || !$password)){
print "\nAttention: mysql connection parameters are missing or not correct!\n";
print "I need you to specify: host, database, user, password;\n";
print "You can do it now typing them right in that order and separeted only by comma;\n";
print "For example:localhost,Pathogens,sandro,xvzhs\n";
print "So, your Mysql connection settings are (type q to quit):";
while (!($db && $mysql =~ /,/) & $mysql ne "q"){
chomp($mysql = <STDIN>);
die "Ok,let's quit this work! Call me when your mind is clearer about Mysql parameters! Bye :-)\n" if $mysql eq "q";
($host,$database,$user,$password) = split (',',$mysql);
$db=Mysql->connect("$host","$database","$user","$password");
last if($db && $mysql =~ /,/);
print "\nMysql connection settings still not correct!\n";
print "Remember: host, database, user, password, separeted only by comma.\n";
print "For example:localhost,Pathogens,sandro,xvzhs\n";
print "Please, try again:";
}
print "Ok, Mysql connection to \"$database\" database was successful!\n";
}
The error message is correct. You are attempting to use a module named , but you never loaded it. Change
use mysql;
to
use Mysql;
to use that module. In the comments, you mention that results in
Can't locate Mysql.pm in #INC
Unless you have reason to believe the module is installed, that indicates it needs to be installed[1]
That module used to be part of the DBD-mysql distribution, but it's obsolete. It's so ancient it was removed from DBD some years ago. To obtain it, you will need to downgrade your DBD-mysql distribution to version 3.0008.
That's pretty awful thing to do. The script should have DBI instead.
cjm points
since the Mysql.pm in 3.0008 is just a compatibility layer using DBI under the hood, you should be able to install Mysql.pm & Mysql/Statement.pm from that old dist along with a current DBD-mysql.
So if you extract Mysql.pm from the distro I linked above as /usr/lib/perl5/Mysql.pm and Mysql/Statement.pm as /usr/lib/perl5/Mysql/Statement.pm, you should have an easy pain-free solution.
In newer versions of Perl, the error message has been improved. It now reads as follows:
Can't locate Mysql.pm in #INC (you may need to install the Mysql module)

Get value of java options in jruby

I'd like to know, in a running jruby script, which java options are set. Is there a way to do this?
My problem is this: There are some scripts that I know require much more memory than others, and I would like to add a constraint in the code so that execution will stop early with proper warnings, rather than running out of memory at some unspecified time in the future.
Perhaps something I could stick in a BEGIN{}, like:
if is_set_joption?('-J-Xmx') then
if get_joption('-J-Xmx').match(/\d+/)[0].to_i < 1000 then
puts "You're gonna run out of memory...";
abort();
end
else
puts "I recommend you start with -J-Xmx1000m.";
abort();
end
(... where is_set_joption? and get_joption are made up methods.)
Running jruby 1.7.8.
It'll be in your ENV if you've set JAVA_OPTS in your environment. You could get it from that.. You've already initiated the JVM at this point though, so you'll want to set that elsewhere, like in your command line when you exec jruby with -D
One can do:
require 'java';
java_import 'java.lang.Runtime';
mxm = Runtime.getRuntime.maxMemory.to_i;
if mxm < (512 * 1024 * 1024) then
raise "You're gonna need a bigger boat.";
end

Verify presence of MySQL driver

I have a perl application that uses a MySQL backend.
How do I verify that the MySQL and database drivers are accessible?
I'm currently doing the following, but I don't know if it is actually a sufficient test -- I'd hate to find out six months down the line that I'm not doing the right test:
use Test::More;
BEGIN { use_ok('DBI'); }
BEGIN { use_ok('DBD::mysql'); }
done_testing();
This is enough to check that connection will be available from Perl side. If you want to check if mysql server is available, you need to connect to it.
P.S. You can also add version checking for DBD::mysql. For ex. 4.001 fixes serious bug in utf8 support.
Well, it looks fine to me, but if you want to be sure, you can check for the presence of the actual filepaths in your %INC ie:
perl -MDBI -e 'die unless $INC{"DBI.pm"}'
perl -MDBD::mysql -e 'die unless $INC{"DBD/mysql.pm"}'

Why is my object.save working in one place and failing in another?

Could someone tell me why this works:
require 'rubygems'
require 'mysql2'
#inverters=Inverter.where(:mac=>#mac)
Inverter.transaction do
#inverters.each do |inverter|
inverter.ip = #client_ip
inverter.save # Object is saved:)!
end
end
But this does not?:
require 'rubygems'
require 'mysql2'
#outputs=<a two dimensional hash>
Output.transaction do
#outputs.each do |out|
#newOut = Output.new
#newOut.inverter_id = out[:inverter_id]
#newOut.eac = out[:eac]
#newOut.pac = out[:pac]
#newOut.vac = out[:vac]
#newOut.iac = out[:iac]
#newOut.epv = out[:epv]
#newOut.ppv = out[:ppv]
#newOut.vpv = out[:vpv]
#newOut.save # Object fails to save to db:(.
# 2 lines of other code
end
end
Both objects save successfully when I enter the same commands manually in the rails console, but the second one fails within my script. I have done extensive debugging making sure that all variables ('out' and '#outputs') have expected values and again it is all working in the console. I am using Ruby 1.8.7, Rails 3.0.3 and mysql2 gem version 0.2.7. Thank you so much in advance!
The first thing I did to figure this out was to open up a separate tab in terminal, navigate to my rails app folder and follow what was going on with mySQL behind the scenes by typing the following line: tail -f log/development.log. I could see on running the second not working script above, in the log that after the INSERT into outputs table line, it would just say 'ROLLBACK'. The reason this was happening was that I had two lines of random code after my #newOut.save statement. When I took those two lines out of the transaction loop, everything worked. This is clearly a total newbie error, but I hope it helps someone.

FreeBSD, MySQL, Perl, bash: intermittent blocking on named pipes?

This is weird and I'm not sure who the culprit really is.
I'm doing some scripting, on FreeBSD (6.2)? which makes extensive use of the following ***bash***ism:
do_something <(mysql --skip-column-names -B -e 'select ... from ... where ...;')
... where "do_something is a somewhat crufty utility (in Perl) that won't read from a pipeline. If I use a regular file it works fine. My bash script using things like exec 4< <(...) with these sorts of queries (following by loops of the form while read x y z <&4; do ... never seem to have any issues.
However, Perl (5.8.x) seems to periodically block (apparently forever). I tried changing out the chomp(my $data = <MYDATA>); with a routine that used sysread and I wrote some test cases in Python for comparison. These seem to block far less often than the idiomatic Perl code, but they still do it sometimes. (The Python code using f.read() or os.read(f.fileno()...) seems to behave about equally in this issue).
I've tried reproducing the issue using ... <(cat ...) (where I'm cating the regular file) and that never seems to reproduce that stall.
I've glanced at some ktrace/kdump data ... but I'm far more familiar with Linux strace or even Solaris truss ... so I haven't figured out what's going from there yet, either.
I suppose we can mostly rule out Perl, because I've reproduced the same issue using Python ... I don't see how the bash could be doing anything wrong here (it's just creating a named pipe in /var/tmp/sh-np-xxx and wiring the processes up to that).
What could the mysql shell/utility be doing that might cause this? I don't think I've seen it from anything else (such as cat or dd). I haven't tested this scenario under Linux ... but I've used <(...) (process substitution) for years under Linux and don't recall ever seeing this.
Is it a FreeBSD issue?
Sure I can work around the issue using temporary files ... but I'd sure rather understand why it's doing this (and avoid some of the races and clean-up messiness that temporary files entail).
Any suggestions?
The big difference between operating on the output of mysql and directly on a file is timing. When the perl process is stalled, the big question is: "why is it not making forward progress"? You can use the "l" option to ps to see the wait channel for the perl process; that way you can see if it blocked on a read, or if something else is going on. If it is really blocked on pipe input, I expect the MWCHAN entry for perl to be "piperd".
The same information would be interesting for the mysql process.
What does your Python test code look like?
Another way of writing this while avoiding the bashism is this; that would allow you to rule out bash:
mysql --skip-column-names -B -e 'select ... from ... where ...;' | do_something /dev/stdin
Other interesting questions:
Does the --unbuffered option to mysql change anything?
Does piping the mysql output through dd change anything? (eg. "perlscript <(mysql ... | dd)
Summary: Need more information.