in reply to Working with DBI and BLOB

This is exactly the purpose behind using strict. Doing so, you would have found that you are placing the actual image data in $img_data, but are trying to put $image_file into the database. Switch either one of the variables and it should work fine.

update: I figured you could use a small rewrite. Some points I covered:

#!perl -w use strict; use DBI; use LWP::Simple; my $img_url = "http://weather.unisys.com/satellite/sat_ir_west.gif"; my $latest_img = "/usr/home/mhearse/weather_images/latest.gif"; my ($min, $hour, $day, $mon, $year) = (localtime())[1..5]; $year += 1900; my $img_name = "$mon-$day-$year-$hour:$min"; my $img_data = get($img_url); die("failed to fetch image from internet!\n"); unless ( defined($img_data) ); open( my $fh_latest, ( -e($latest_img) ? '+<' : '+>' ), $latest_img ) or die("could not open file: $!"); binmode($fh_latest); my $latest_data = do { local $/; <$fh_latest> }; if ($latest_data ne $img_data) { seek($fh_latest, 0, 0); truncate($fh_latest, 0); print $fh_latest $img_data; my $dbh = DBI->connect( 'dbi:mysql:weather_images', 'user', 'secret', { RaiseError => 1, AutoCommit => 1 } ); $dbh->do( 'INSERT INTO gw_ir (image_name, image_file) VALUES(?,?)', undef, $img_name, $img_data ); $dbh->disconnect(); warn("File was not current; updates made.\n"); } else { warn("File was current, no updates made.\n"); }

Replies are listed 'Best First'.
Re^2: Working with DBI and BLOB
by mhearse (Chaplain) on Dec 24, 2004 at 21:46 UTC
    You're right, that was sloppy. Here is a revision:
    mysql> describe gw_ir; +------------+-------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +------------+-------------+------+-----+---------+----------------+ | image_id | int(11) | | PRI | NULL | auto_increment | | image_name | varchar(50) | YES | | NULL | | | image_data | mediumblob | YES | | NULL | | +------------+-------------+------+-----+---------+----------------+ 3 rows in set (0.00 sec)
    #!/usr/bin/perl use strict; use LWP::Simple; use DBI; my $url = "http://weather.unisys.com/satellite/sat_ir_west.gif"; my $file = "/usr/home/mhearse/weather_images/sat_ir_west.gif"; my $newfile = "/usr/home/mhearse/weather_images/latest.gif"; my ($min, $hour, $day, $month, $year) = (localtime)[1,2,3,4,5]; my $image_name = "$month-$day-$year-$hour:$min"; getstore($url, $file); if (-s $file != -s $newfile) { rename $file, $newfile; my $image_data = getFile($newfile); my $dbh = DBI->connect("dbi:mysql:weather_images", "ser", "********") or die("Error! $!\nAborting"); my $sql = qq(INSERT INTO gw_ir (image_name, image_data) VALUES ("$image_name", "$image_data")); my $sth = $dbh->prepare($sql); $sth->execute or die("\nError executing SQL statement! $DBI::errstr +"); $dbh->disconnect; } else { print "file is current\n"; } sub getFile { my($file) = @_; my $fh; unless (open $fh, "<", $file) { die "Error opening $file : $!\n"; } my $data; { local $/ = undef; $data = <$fh>; } close $fh; return $data; }
    MySQL doesn't like the sql statement.
    DBD::mysql::st execute failed: You have an error in your SQL syntax. +Check the manual that corresponds to your MySQL server version for th +e right syntax to use near 'ÀµÖ* íÆ. ³ô®´ØR{mþÒ:»Àºëö*·ì¶k¼½.àë·' at +line 3 at ./simple line 24. Error executing SQL statement! You have an error in your SQL syntax. +Check the manual that corresponds to your MySQL server version for th +e right syntax to use near 'ÀµÖ* íÆ. ³ô®´ØR{mþÒ:»Àºëö*·ì¶k¼½.àë·' at +line 3 at ./simple line 24.
      Just for correctness reasons, the reason this attempt doesn't work is that you attempt to interpolate the unescaped image data directly in to your sql statement. This is bad. Use placeholders, or at least dbi->quote.
Re^2: Working with DBI and BLOB
by mhearse (Chaplain) on Dec 24, 2004 at 21:52 UTC
    Your rewrite works flawlessly! Thanks much. You can disregard my previous reply.

      Actually, as a final "fix" to the whole thing -- do you actually need the latest image file to be kept on the file system, or are you just keeping it there to compare against the next fetch? If you do not need the image on the file system, you can bypass that altogether and just use the database:

      #!perl -w use strict; use DBI; use LWP::Simple; my $img_url = "http://weather.unisys.com/satellite/sat_ir_west.gif"; my $dbh = DBI->connect( 'dbi:mysql:weather_images', 'user', 'secret', { RaiseError => 1, AutoCommit => 1 } ); my ($min, $hour, $day, $mon, $year) = (localtime())[1..5]; $year += 1900; my $img_name = "$mon-$day-$year-$hour:$min"; my $img_data = get($img_url); die("failed to fetch image from internet!\n") unless ( defined($img_data) ); # fetch the last row we added to the table my $latest_entry = $dbh->selectrow_arrayref( 'SELECT image_file FROM gw_ir ORDER BY image_id DESC LIMIT 1' ); # either no data in database or the file contents # have changed since the last update if (not defined($latest_entry) or $latest_entry->[0] ne $img_data) { $dbh->do( 'INSERT INTO gw_ir (image_name, image_file) VALUES(?,?)', undef, $img_name, $img_data ); warn("File was not current; updates made.\n"); } else { warn("File was current, no updates made.\n"); } $dbh->disconnect();

      And even if you do need the file system file, it might even be better to use the database anyway and then output the file:

      #!perl -w use strict; use DBI; use LWP::Simple; my $img_url = "http://weather.unisys.com/satellite/sat_ir_west.gif"; my $local_img = "/usr/home/mhearse/weather_images/latest.gif"; my $dbh = DBI->connect( 'dbi:mysql:weather_images', 'user', 'secret', { RaiseError => 1, AutoCommit => 1 } ); my ($min, $hour, $day, $mon, $year) = (localtime())[1..5]; $year += 1900; my $img_name = "$mon-$day-$year-$hour:$min"; my $img_data = get($img_url); die("failed to fetch image from internet!\n") unless ( defined($img_data) ); # fetch the last row we added to the table my $latest_entry = $dbh->selectrow_arrayref( 'SELECT image_file FROM gw_ir ORDER BY image_id DESC LIMIT 1' ); # either no data in database or the file contents # have changed since the last update if (not defined($latest_entry) or $latest_entry->[0] ne $img_data) { open( my $fh, '>', $local_img ) or die("could not open file: $!"); binmode($fh); print $fh $img_data; $dbh->do( 'INSERT INTO gw_ir (image_name, image_file) VALUES(?,?)', undef, $img_name, $img_data ); warn("File was not current; updates made.\n"); } else { warn("File was current, no updates made.\n"); } $dbh->disconnect();