File Coverage

blib/lib/IO/BLOB/Pg.pm
Criterion Covered Total %
statement 18 218 8.2
branch 0 92 0.0
condition 0 26 0.0
subroutine 6 34 17.6
pod 5 23 21.7
total 29 393 7.3


line stmt bran cond sub pod time code
1             package IO::BLOB::Pg;
2              
3             # Copyright 2000 Mark A. Hershberger
4             #
5             # This library is free software; you can redistribute it and/or
6             # modify it under the same terms as Perl itself.
7              
8             require 5.005_03;
9 7     7   198820 use strict;
  7         19  
  7         332  
10 7     7   38 use vars qw($VERSION $DEBUG $IO_CONSTANTS);
  7         16  
  7         2025  
11             $VERSION = "0.91"; # $Date: 2002/08/12 06:14:57 $
12              
13 7     7   7525 use Symbol ();
  7         7729  
  7         178  
14 7     7   44 use Carp;
  7         13  
  7         691  
15 7     7   7585 use IO::Handle;
  7         48038  
  7         12827  
16              
17             my $SEEK_SET = &IO::Handle::SEEK_SET;
18             my $SEEK_END = &IO::Handle::SEEK_END;
19              
20             sub new
21             {
22 0     0 1   my $class = shift;
23 0   0       my $self = bless Symbol::gensym(), ref($class) || $class;
24              
25 0           tie *$self, $self;
26 0 0         return $self->open(@_) ? $self : undef;
27             }
28              
29             sub open
30             {
31 0     0 1   my $self = shift;
32 0 0         return $self->new(@_) unless ref($self);
33              
34 0 0         if (@_ == 2) {
    0          
35 0           *$self->{dbi} = $_[0];
36 0           *$self->{id} = $_[1];
37             } elsif(@_ == 1) {
38 0           *$self->{dbi} = $_[0];
39 0           *$self->{id} = *$self->{dbi}->func(*$self->{dbi}->{pg_INV_READ} |
40             *$self->{dbi}->{pg_INV_WRITE}, "lo_creat");
41             } else {
42 0           croak "open \$DBI[, \$id]";
43             }
44 0 0         croak "AutoCommit needs to be off"
45             if *$self->{dbi}->{AutoCommit};
46 0           *$self->{fh} = *$self->{dbi}->func(*$self->{id},
47             *$self->{dbi}->{pg_INV_READ} |
48             *$self->{dbi}->{pg_INV_WRITE}, "lo_open");
49              
50 0 0 0       if(not defined *$self->{fh} || not defined *$self->{id}) {
51 0           return undef;
52             }
53 0           *$self->{pos} = 0;
54 0           *$self->{lno} = 0;
55              
56 0           $self;
57             }
58              
59             sub oid {
60 0     0 1   my $self = shift;
61 0           return *$self->{id};
62             }
63              
64             sub pad {
65 0     0 1   my $self = shift;
66 0           my $old = *$self->{pad};
67 0 0         *$self->{pad} = substr($_[0], 0, 1) if @_;
68 0 0 0       return "\0" unless defined($old) && length($old);
69 0           $old;
70             }
71              
72             sub dump
73             {
74 0     0 0   require Data::Dumper;
75 0           my $self = shift;
76 0           print Data::Dumper->Dump([$self], ['*self']);
77 0           print Data::Dumper->Dump([*$self{HASH}], ['$self{HASH}']);
78             }
79              
80             sub TIEHANDLE
81             {
82 0 0   0     print "TIEHANDLE @_\n" if $DEBUG;
83 0 0         return $_[0] if ref($_[0]);
84 0           my $class = shift;
85 0           my $self = bless Symbol::gensym(), $class;
86 0           $self->open(@_);
87 0           $self;
88             }
89              
90             sub DESTROY
91             {
92 0 0   0     print "DESTROY @_\n" if $DEBUG;
93             }
94              
95             sub close
96             {
97 0     0 0   my $self = shift;
98 0 0 0       *$self->{dbi}->func(*$self->{fh}, 'lo_close')
99             if defined (*$self->{dbi} && defined *$self->{fh});
100 0           delete *$self->{buf};
101 0           delete *$self->{pos};
102 0           delete *$self->{lno};
103              
104 0           $self;
105             }
106              
107             sub opened
108             {
109 0     0 0   my $self = shift;
110 0           defined *$self->{buf};
111             }
112              
113             sub getc
114             {
115 0     0 0   my $self = shift;
116 0           my $buf;
117 0 0         return $buf if $self->read($buf, 1);
118 0           return undef;
119             }
120              
121             sub ungetc
122             {
123 0     0 0   my $self = shift;
124 0           $self->setpos($self->getpos() - 1)
125             }
126              
127             sub eof
128             {
129 0     0 0   my $self = shift;
130 0           my $dbi = *$self->{dbi};
131 0           my $id = *$self->{id};
132 0           my $tmp = $self->tell;
133 0           $self->seek(0, 2);
134 0           my $end = $self->tell;
135 0           $self->seek($tmp, 0);
136              
137 0           $end <= $tmp;
138             }
139              
140             sub print
141             {
142 0     0 0   my $self = shift;
143 0 0         if (defined $\) {
144 0 0         if (defined $,) {
145 0           $self->write(join($,, @_).$\);
146             } else {
147 0           $self->write(join("",@_).$\);
148             }
149             } else {
150 0 0         if (defined $,) {
151 0           $self->write(join($,, @_));
152             } else {
153 0           $self->write(join("",@_));
154             }
155             }
156             }
157             *printflush = \*print;
158              
159             sub printf
160             {
161 0     0 0   my $self = shift;
162 0 0         print "PRINTF(@_)\n" if $DEBUG;
163 0           my $fmt = shift;
164 0           $self->write(sprintf($fmt, @_));
165             }
166              
167              
168             sub seek {
169 0     0 0   my($self,$off,$whence) = @_;
170 0           my $fh = *$self->{fh};
171 0           my $pos;
172              
173 0           $pos = *$self->{dbi}->func($fh, $off, $whence, 'lo_lseek');
174 0 0 0       carp "Error during seek: ", $DBI::errstr
175             if $DBI::err || not defined $pos;
176              
177 0 0 0       if(defined $pos && $pos < 0) {
    0          
178 0           $pos = 0;
179 0           *$self->{lno} = 0;
180             } elsif(defined $pos) {
181 0           *$self->{pos} = $pos;
182             }
183 0 0         return 1 if defined $pos;
184 0           return 0;
185             }
186              
187             sub _length {
188 0     0     my $self = shift;
189 0           my $old = *$self->{pos};
190              
191 0           $self->seek(0, 2);
192 0           my $len = $self->tell;
193 0           $self->seek($old, 0);
194              
195 0           return $len;
196             }
197             *length = \&_length;
198              
199             sub pos {
200 0     0 1   my $self = shift;
201 0           my $old = *$self->{pos};
202 0 0         _init_seek_constants() unless defined $SEEK_SET;
203              
204 0 0         if (@_) {
205 0   0       my $pos = shift || 0;
206 0           my $fh = *$self->{fh};
207 0           my $len = $self->_length;
208 0 0         $pos = $pos > $len ? $len : $pos;
209 0           *$self->{dbi}->func($fh, $pos, $SEEK_SET, 'lo_lseek');
210 0           *$self->{pos} = $pos;
211 0           *$self->{lno} = 0;
212             }
213 0           $old;
214             }
215              
216 0     0 0   sub getpos { shift->pos; }
217              
218             *sysseek = \&seek;
219             *setpos = \&pos;
220             *tell = \&getpos;
221              
222              
223              
224             sub getline
225             {
226 0     0 0   my $self = shift;
227 0           my $fh = *$self->{fh};
228 0           my $dbi = *$self->{dbi};
229 0           my $len = $self->_length();
230 0           my $pos = *$self->{pos};
231 0 0         return if $pos >= $len;
232 0           my $line = "";
233              
234 0 0         unless (defined $/) { # slurp
235 0           *$self->{pos} = $len;
236 0           $dbi->func($fh, $line, $len - $pos, 'lo_read');
237 0           return $line;
238             }
239              
240 0 0         unless (length $/) { # paragraph mode
241             # XXX slow&lazy implementation using getc()
242 0           my $para = "";
243 0           my $eol = 0;
244 0           my $c;
245 0           while (defined($c = $self->getc)) {
246 0 0         if ($c eq "\n") {
    0          
247 0           $eol++;
248             } elsif ($eol > 1) {
249 0           $self->ungetc($c);
250 0           last;
251             }
252 0           $para .= $c;
253             }
254 0           return $para; # XXX wantarray
255             }
256              
257 0           my $ret = "";
258 0           my $tmp = "";
259 0           my $br;
260             READ:
261 0           while (($br = $self->read($tmp, 512)) != 0) {
262 0           my $idx = index($tmp, $/);
263 7 0   7   7192 if($idx > ($[ - 1)) {
  7         3322  
  7         8948  
  0            
264 0           *$self->{pos} += $idx + length($/) - $br;
265 0           $self->seek(*$self->{pos}, 0);
266 0           $ret .= substr($tmp, 0, $idx+length($/));
267 0           $. = ++*$self->{lno};
268 0           return $ret;
269             } else {
270 0           $ret .= $tmp;
271 0           *$self->{pos} += $br
272             }
273             }
274 0           $. = ++*$self->{lno};
275              
276 0           return $ret;
277             }
278              
279             sub getlines
280             {
281 0 0   0 0   die "getlines() called in scalar context\n" unless wantarray;
282 0           my $self = shift;
283 0           my($line, @lines);
284 0           push(@lines, $line) while defined($line = $self->getline);
285 0           return @lines;
286             }
287              
288             sub READLINE
289             {
290 0 0   0     goto &getlines if wantarray;
291 0           goto &getline;
292             }
293              
294             sub input_line_number
295             {
296 0     0 0   my $self = shift;
297 0           my $old = *$self->{lno};
298 0 0         *$self->{lno} = shift if @_;
299              
300 0           $old;
301             }
302              
303             sub truncate {
304 0     0 0   my $self = shift;
305 0   0       my $len = shift || 0;
306 0           my $fh = *$self->{fh};
307 0 0         if ($self->_length > $len) {
    0          
308 0           carp "Not Implemented";
309             # substr($fh, $len) = '';
310             # *$self->{pos} = $len if $len < *$self->{pos};
311             } elsif ($self->_length < $len) {
312 0           $self->seek(0, $SEEK_END);
313 0           $self->write($self->pad x ($len - $self->_length))
314             }
315 0           $self;
316             }
317              
318             sub read
319             {
320 0     0 0   my $self = shift;
321 0           my $fh = *$self->{fh};
322 0           my $dbi = *$self->{dbi};
323 0           my $tbuf = "";
324 0           my $len = $_[1];
325 0           my $pos = *$self->{pos};
326 0           my $rem = $self->_length - $pos;
327              
328 0           my $nbytes = $dbi->func($fh, $tbuf, $len, "lo_read");
329              
330 0 0         if (@_ > 2) { # read offset
331 0           substr($_[0],$_[2]) = $tbuf;
332             } else {
333 0           $_[0] = $tbuf;
334             }
335 0           *$self->{pos} += $nbytes;
336 0           return $nbytes
337             }
338              
339             sub write
340             {
341 0     0 0   my $self = shift;
342 0           my $fh = *$self->{fh};
343 0           my $dbi = *$self->{dbi};
344              
345 0           my $pos = *$self->{pos};
346 0           my $slen = length($_[0]);
347 0           my $len = $slen;
348 0           my $off = 0;
349 0 0         if (@_ > 1) {
350 0 0         $len = $_[1] if $_[1] < $len;
351 0 0         if (@_ > 2) {
352 0   0       $off = $_[2] || 0;
353 0 0         die "Offset outside file" if $off > $slen;
354 0 0         if ($off < 0) {
355 0           $off += $slen;
356 0 0         die "Offset outside file" if $off < 0;
357             }
358 0           my $rem = $slen - $off;
359 0 0         $len = $rem if $rem < $len;
360             }
361             }
362              
363 0           my $nbytes = $dbi->func($fh, substr($_[0], $off), $len, "lo_write");
364 0           *$self->{pos} += $nbytes;
365 0           $nbytes;
366             }
367              
368             *sysread = \&read;
369             *syswrite = \&write;
370              
371             sub stat
372             {
373 0     0 0   my $self = shift;
374 0 0         return unless $self->opened;
375 0 0         return 1 unless wantarray;
376 0           my $len = $self->_length;
377              
378             return (
379             undef, undef, # dev, ino
380 0           0666, # filemode
381             1, # links
382             $>, # user id
383             $), # group id
384             undef, # device id
385             $len, # size
386             undef, # atime
387             undef, # mtime
388             undef, # ctime
389             512, # blksize
390             int(($len+511)/512) # blocks
391             );
392             }
393              
394             sub blocking {
395 0     0 0   my $self = shift;
396 0   0       my $old = *$self->{blocking} || 0;
397 0 0         *$self->{blocking} = shift if @_;
398 0           $old;
399             }
400              
401 0     0     my $notmuch = sub { return };
402              
403             *fileno = $notmuch;
404             *error = $notmuch;
405             *clearerr = $notmuch;
406             *sync = $notmuch;
407             *flush = $notmuch;
408             *setbuf = $notmuch;
409             *setvbuf = $notmuch;
410              
411             *untaint = $notmuch;
412             *autoflush = $notmuch;
413             *fcntl = $notmuch;
414             *ioctl = $notmuch;
415              
416             *GETC = \&getc;
417             *PRINT = \&print;
418             *PRINTF = \&printf;
419             *READ = \&read;
420             *WRITE = \&write;
421             *CLOSE = \&close;
422              
423             1;
424              
425             __END__