Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical

DBD::CSV, SQL::Statement, and UPDATE table statement

by Tanktalus (Canon)
on May 18, 2005 at 03:38 UTC ( #458059=perlquestion: print w/replies, xml ) Need Help??
Tanktalus has asked for the wisdom of the Perl Monks concerning the following question:

I'm in the process of moving some of my stuff over from one Linux box to a newer box. During this transition, one of the scripts I use regularly does something like this (greatly simplified for posting purposes):

#! /usr/bin/perl -w use strict; use DBI; use FindBin; my $new_total = 10; open my $fh, '>', $FindBin::Bin . '/data'; print $fh ("DATE,NUMBER\n2005-05-16,2\n2005-05-17,4\n"); close $fh; my $dbh = DBI->connect('dbi:CSV:f_dir=' . $FindBin::Bin . ";csv_eol=\n +") or warn "Can't connect to DBI"; my $total = $dbh->selectall_arrayref('select sum(number) from data')-> +[0][0]; if ($total||0 != $new_total) { require Time::localtime; my $lt = Time::localtime::localtime(time(); my $date = sprintf("%04d-%02d-%02d", $lt->year + 1900, $lt->mon + +1, $lt->mday); my $count = $dbh->selectall_arrayref('select count(*) from data wh +ere date = ?', {}, $date)->[0][0]; my $cur = $dbh->selectall_arrayref('select number from data where +date = ?', {}, $date); $cur = $cur->[0] while $cur and ref $cur; my $gained = $new_total - ($total||0); if ($count) { $cur += $gained; print "Updating today ($date) to be Number = $cur\n"; $dbh->do('update data set number = ? where date = ?', {}, $cur +, $date); } else { $cur = $gained; print "Inserting into today to be Number = $cur\n"; $dbh->do('insert into data (date,number) values(?,?)', {}, $da +te,$cur); } }
In this example code, lines 9 through 11 create a sample CSV data file - if your local time when you try this is not in the sample data, add it. The problem only exists in the update scenario, not the insert scenario, and I want to make as self-contained of an example as possible. The rest of the code is pretty much the same as what I'm using, but obviously doesn't work. I expect the file 'data' to look like this afterwards:
DATE,NUMBER 2005-05-16,2 2005-05-17,8
However, it actually looks like this:
DATE,NUMBER 2005-05-16,2 2005-05-17,2005-05-17
I'm using:
$ perl -MDBD::CSV -e 'print "perl\t$]\n"; print $_,"\t",${$_."::VERSIO +N"},$/ foreach @ARGV' DBD::CSV SQL::Statement SQL::Parser Text::CSV_X +S SQL::Statement::Util perl 5.008005 DBD::CSV 0.22 SQL::Statement 1.14 SQL::Parser 1.13 Text::CSV_XS 0.23 SQL::Statement::Util -1, set by
On another machine, the same command returns:
perl 5.008006 DBD::CSV 0.21 SQL::Statement 1.09 SQL::Parser 1.09 Text::CSV_XS 0.23 SQL::Statement::Util
and the update works fine. I suspect a problem in DBD::CSV, SQL::Statement, or SQL::Parser, but I'm not sure how to figure it out for sure. I suppose my workaround is to either find a way to uninstall these and install the older versions (which is kind of a pain), or to delete/reinsert rather than use update. Or maybe to get rid of the ?'s and put my number right in the string - which isn't that bad in my case, but if I'm really encountering a bug, I wouldn't want tossing ?'s out of one's repertoire to be the standard response...

If anyone has any other considerations, I'd be open to them. Otherwise, I'll submit this to the current maintainer of DBD::CSV (who will probably forward it on somewhere else, but that's as far as I understand this situation at the moment). Thanks!

Replies are listed 'Best First'.
Re: DBD::CSV, SQL::Statement, and UPDATE table statement
by jZed (Prior) on May 18, 2005 at 04:08 UTC
    Well, since, I'm the maintainer of all of those modules, I don't really have anywhere to pass it on to :-). Testing as we speak, I'll update when I have an answer and please /msg if you find something out in the meantime.


    Very, very odd. I got the same fubared results you did. But when I run the test below (which uses all the same SQL as yours), everything is copacetic. More later.
    #! /usr/bin/perl -w use strict; use DBI; use FindBin; open my $fh, '>', $FindBin::Bin . '/Tanktalus'; print $fh ("DATE,NUMBER\n2005-05-16,2\n2005-05-17,4\n"); close $fh; my $dbh = DBI->connect("dbi:CSV(RaiseError=1):csv_eol=\n"); for my $sql(<DATA>){ my $sth = $dbh->prepare($sql); $sth->execute; $sth->dump_results if $sth->{NUM_OF_FIELDS}; } __END__ SELECT date,number FROM Tanktalus SELECT SUM(number) from Tanktalus UPDATE Tanktalus SET number=8 WHERE date='2005-05-17' SELECT date,number FROM Tanktalus SELECT SUM(number) from Tanktalus SELECT number FROM Tanktalus WHERE date = '2005-05-17'


    Ok, I can reproduce the error by using placeholders for the update in the script above. It's a SQL::Statement problem. Fix coming by morning.


    Ok, I found and fixed the bug in SQL::Statement. Please try grab the latest from the SVN repository and let me know if it works for you. I thanked you for the bug report in the Changes log of the distro.

      Thanks, jZed. Works much better now. Definitely wasn't a module I was expecting to get my name into ;-)

      I didn't like not using the placeholders, so I'm glad to have this fixed :-)

        Is there any schedule for getting this version into CPAN?

        I spent today tracking down another version of this bug exposed via Class::DBI and DBD::AnyData, it's nice to know that it's been fixed and that I'm not crazy (ok, at least that it's been fixed...).


Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://458059]
Approved by kvale
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (10)
As of 2017-11-24 12:24 GMT
Find Nodes?
    Voting Booth?
    In order to be able to say "I know Perl", you must have:

    Results (348 votes). Check out past polls.