Improv has asked for the wisdom of the Perl Monks concerning the following question:

I am working on making a script to import data from various programming projects into a Postgres database running on a different machine. I've used the lo_ functions (database is Postgresql) to import the data into pg_largeobject, but now I have another table that I want to update:
create table patblob (name varchar(20), id oid);
Whenever I try to insert into that table
print "Try: insert into patblob values ('Yo', $blobid)\n"; $boo = $dbh->prepare("insert into patblob values ('Yo',$blobid)"); $boo->execute; $dbh->commit;
The insert fails, even though the blobid is good and the interactive psql tool can make the exact same insert ok.

Replies are listed 'Best First'.
Re: DBI and BLOBs
by hardburn (Abbot) on Mar 24, 2003 at 15:44 UTC

    You should really be using placeholders, specify your table entries explicitly, and check the return value of $dbh->prepare and $dbh->execute:

    use strict; my $boo = $dbh->prepare('INSERT INTO patblob (varchar, id) VALUES (?, +?)') or die "Database error: " . $dbh->errstr; $boo->execute('Yo', $blobid) or die "Database error: " . $dbh->errstr; $dbh->commit; $boo->finish();

    The above code is safer and should give you proper error messages on failure. It's hard to debug code when you don't have proper error messages.

    Update: Forgot something. It appears that $blobid is a BLOB, but you're inserting it into a numeric field. Huh?

    ----
    Reinvent a rounder wheel.

    Note: All code is untested, unless otherwise stated

      That's a PostgreSQL thing. If you instert a large object into the database you get a OID identifier. It refer to this later you need to stash the OID somewhere and that is exactly what the original poster is doing. OIDs look like integers but aren't exactly that hence my explicit cast to the oid type. Of course, the original poster should be dumping the insert statements somewhere so the syntax can be verified.

      Here's the whole block with your changes (it still fails):
      sub do_blob { my $myblob = shift; my $blobid = $dbh->func($dbh->{pg_INV_WRITE}, 'lo_creat'); print "Created $blobid\n"; $dbh->{AutoCommit} = 0; my $blobfd = $dbh->func($blobid, $dbh->{pg_INV_WRITE}, 'lo_open'); print "Blobfd $blobfd\n"; my $nb = $dbh->func($blobfd, $myblob, length($myblob), 'lo_write'); $dbh->commit; if($nb == 0) {warn "Why?!?! : $!\n";} $dbh->func($blobfd, 'lo_close'); $blobid += 0; print "Try: insert into patblob values ('Yo', $blobid)\n"; $boo = $dbh->prepare("insert into patblob (name,id) values (?, ?)") or + die "DB Err: " . $dbh->errstr; print "Prepped\n"; $boo->execute('Yo', $blobid) or die "Execute error: " . $dbh->errstr; print "Executed\n"; $dbh->commit; $boo->finish(); }
      I think $blobid is numeric -- here's the output:
      Created 186811 Blobfd 0 Try: insert into patblob values ('Yo', 186811) Prepped NOTICE: current transaction is aborted, queries ignored until end of +transaction block Executed
      I added that += 0 part recently to make sure that perl knows that $blobid is meant to be numeric.. Thanks for your help..
        Apparently, it's not at all kosher to have your lo_close in a seperate transaction from your other lo_functions, and that arrangement (which was accidental) broke things. In case anyone's interested, the simple fix is to scoot the $dbh->func($blobfd, 'lo_close'); and the line before it up above that $dbh->commit;
Re: DBI and BLOBs
by dga (Hermit) on Mar 24, 2003 at 15:52 UTC

    I have not worked with BLOBs in PostgreSQL, but I have inserted large obejects into the database. In PostgreSQL 7.1 and later (maybe 7.0 also, I forget) the text field can hold really large data pieces. I have stored photos in text fields. They were thumbnail size of about 20-30 kb in size. Text fields only hold text so I used MIME::Base64 to convert my images to/from text at write/read time.

    In short, there are situations where the overhead of blob processing is unneeded. I have in testing put Base64 text of over a megabyte in a PostgreSQL field.

    One caveat is SELECT * from table; with these monster fields embedded in the table.Also the object will have to exist in your programs data space both on insert and extract whereas blobs can be loaded directly to and from flat files.

Re: DBI and BLOBs
by diotalevi (Canon) on Mar 24, 2003 at 15:46 UTC

    OID is integer-ish. Consider changing your code to explicitly case your OID to oid. $blobid::oid

      I'm sorry -- I don't understand this at all. $blobid::oid would be $oid in the blobid:: namespace, I think.

        Oh I'm sorry. See, I forgot the '::oid' part would be interpreted as part of the variable name. Its not. One of the ways you type a variable is to append it following a double colon. So 12345::integer and 'this is a text field'::text are valid PostgreSQL constructs. I suggested you write "insert into patblob values ('Yo'," . $blobid . "::oid)" this. I just moved $blobid out of the string so its obvious which parts are SQL and which parts are perl.