NAME
DBIx::BLOB::Handle - Read Database Large Object Binaries
from file handles
SYNOPSIS
use DBI;
use DBIx::BLOB::Handle;
# use DBIx::BLOB::Handle qw( :INTO_STATEMENT );
$dbh = DBI->connect('DBI:Oracle:ORCL','scott','tiger',
{RaiseError => 1, PrintError => 0 }
)
or die 'Could not connect to database:' , DBI->errstr;
$dbh->{LongTruncOk} = 1; # very important!
$sql = 'select mylob from mytable where id = 1';
$sth = $dbh->prepare($sql);
$sth->execute;
$sth->fetch;
$fh = DBIx::BLOB::Handle->new($sth,0,4096);
...
print while <$fh>;
# print $fh->getlines;
print STDERR 'Size of LOB was ' . $fh->tell . " bytes\n";
...
# read default buffer size
# fastest way to process a LOB
print $chunk while read($fh,$chunk,undef);
...
# fastest way to read a LOB into a scalar
local $/;
$blob = <$handle>;
...
# or if we used the dangerous :INTO_STATEMENT pragma,
# we could say:
# $fh = $sth->blob_as_handle(0,4096);
...
$sth->finish;
$dbh->disconnect;
DESCRIPTION AND RATIONALE
DBI has a blob_copy_to_file method which takes a file han-
dle argument and copies a database large object binary
(LOB) to this file handle. However, the method is undocu-
mented and faulty. Constructing a similar method yourself
is pretty simple but what if you wished to read the data
and perform operations on it? You could use the DBI's
blob_read method yourself to process chunks of data from
the LOB or even dump its contents into a scalar, but maybe
it would be nice to read the data line by line or piece by
piece from a familiar old filehandle?!
DBIx::BLOB::Handle constructs a tied filehandle that also
extends from IO::Handle and IO::Selectable. It wraps DBI's
blob_read method. By making LOB's available as a file han-
dle to read from we can process the data in a familiar
(perly) way.
Additionally, by making the module respect $/ and $. then
we can read lines of text data from a textual LOB (CLOB)
and treat it just as we would any other file handle!
CONSTRUCTOR
new
$fh = DBIx::BLOB::Handle->new($sth,$column,$block-
size);
$fh = $statement->blob_as_handle($column,$blocksize);
Constructs a new file handle from the given DBI statement,
given the column number (zero based) of the LOB within the
statement. The column number defaults to '0'. The block-
size argument specifies how many bytes at a time should be
read from the LOB and defaults to '4096'
...
By 'use'ing the :INTO_STATEMENT pragma as follows;
use DBIx::BLOB::Handle qw( :INTO_STATEMENT );
DBIx::BLOB::Handle will install itself as a method of the
DBI::st (statement) class. Thus you can create a file han-
dle by calling
$fh = $statement->blob_as_handle($column,$blocksize);
which in turn calls new.
METHODS
readline
$line = $handle->getline;
$line = scalar <$handle>;
@lines = $handle->getlines;
@lines = <$handle>;
Read from the LOB. $handle->getline, or <$handle> in
scalar context will return a line, according to the
current definition of a line (everything up to the
next value of $/); $handle->getlines or <$handle> in
list context will return an array of lines.
Note: the actual implementation is to do a read (see
below) at the default blocksize. The data read back is
then split to find the actual rows. Thus there is a
trade off between number of network reads performed
and the amount of storage on the client.
Bug: Mixing reads and readlines on the same handle
will screw everything up! This is because the stored
position within the blob is the position from the last
read, not the number of bytes from the currently
returned lines.
getc
$char = $handle->getc;
$char = getc $handle;
Returns the next byte from $handle. Returns undef if
there are no more bytes to read. This is SLOW as it
fetches one byte from the database each time. A future
implementation might fetch the default (blocksize)
number of bytes from the database and then return
these as single characters. Thoughts anyone?
read
$handle->read($chunk,[$length], [$offset]);
read $handle, $chunk, $length, [$offset];
Read $length bytes from $handle into $chunk, starting
at position $offset in $chunk (thus you can build up a
scalar data structure). If $length is omitted then the
default blocksize will be used. If $length is omitted
then the bytes read will fill $chunk. Returns the num-
ber of bytes read.
seek
$handle->seek($offset, $whence);
seek $handle $offset, $whence;
Positions the file pointer for $handle. The first
position is 0, not 1. Units are bytes, not line num-
bers; $whence specifies what file position $offset
uses; 0, the beginning of the file; 1, the current
position; or 2, the end of the file.
Note: The behaviour currently differs from that of a
standard file handle. Seeking before the beginning or
after then end of the handle will reset the handle
position to the beginning or end respectively.
Note: Seeking backwards for $handle is efficient
because we don't have to do any further network traf-
fic. Seeking forward means we have to do more reads
from the blob as i am unaware of any (database inde-
pendant) method to get the size of a LOB. Currently
reads are NOT cached since we don't know the final
size of the blob. Thus seeking to the end of the blob,
and then reading it backward or reading the entire
blob, seeking to position 0 and re-reading (as exam-
ples) would result in double the amount of network
traffic.
tell
$handle->tell;
tell $handle;
Gives the current position (in bytes, zero based)
within the LOB
eof $handle->eof;
eof $handle;
Returns true if we have finished reading from the LOB.
SEE ALSO
Perls Filehandle functions, The Tied Handle interface, the
IO::Handle manpage, the IO::Seekable manpage
BUGS
Don't use the read method and the readline methods on the
same handle.
Otherwise please report them!
AUTHOR
Mark Southern (
[email protected])
COPYRIGHT
Copyright (c) 2002, Merck & Co. Inc. All Rights Reserved.
This module is free software. It may be used, redis-
tributed and/or modified under the terms of the Perl
Artistic License (see
http://www.perl.com/perl/misc/Artis-
tic.html)