File Coverage

blib/lib/Fsdb/Filter/dbrow.pm
Criterion Covered Total %
statement 15 55 27.2
branch 0 12 0.0
condition n/a
subroutine 5 14 35.7
pod 5 5 100.0
total 25 86 29.0


line stmt bran cond sub pod time code
1             #!/usr/bin/perl
2              
3             #
4             # dbrow.pm
5             # Copyright (C) 1991-2007 by John Heidemann
6             # $Id: 3fe478660267a8bb5a9f13c957e1169ae188226e $
7             #
8             # This program is distributed under terms of the GNU general
9             # public license, version 2. See the file COPYING
10             # in $dblibdir for details.
11             #
12              
13             package Fsdb::Filter::dbrow;
14              
15             =head1 NAME
16              
17             dbrow - select rows from an Fsdb file based on arbitrary conditions
18              
19             =head1 SYNOPSIS
20              
21             dbrow [-vw] CONDITION [CONDITION...]
22              
23             =head1 DESCRIPTION
24              
25             Select rows for which all CONDITIONS are true.
26             Conditions are specified as Perl code,
27             in which column names are be embedded, preceded by underscores.
28              
29             =head1 OPTIONS
30              
31             =over 4
32              
33             =item B<-v>
34              
35             Invert the selection, picking rows where at least one condition does
36             I match.
37              
38             =back
39              
40             =for comment
41             begin_standard_fsdb_options
42              
43             This module also supports the standard fsdb options:
44              
45             =over 4
46              
47             =item B<-d>
48              
49             Enable debugging output.
50              
51             =item B<-w> or B<--warnings>
52              
53             Enable warnings in user supplied code.
54              
55             =item B<-i> or B<--input> InputSource
56              
57             Read from InputSource, typically a file name, or C<-> for standard input,
58             or (if in Perl) a IO::Handle, Fsdb::IO or Fsdb::BoundedQueue objects.
59              
60             =item B<-o> or B<--output> OutputDestination
61              
62             Write to OutputDestination, typically a file name, or C<-> for standard output,
63             or (if in Perl) a IO::Handle, Fsdb::IO or Fsdb::BoundedQueue objects.
64              
65             =item B<--autorun> or B<--noautorun>
66              
67             By default, programs process automatically,
68             but Fsdb::Filter objects in Perl do not run until you invoke
69             the run() method.
70             The C<--(no)autorun> option controls that behavior within Perl.
71              
72             =item B<--help>
73              
74             Show help.
75              
76             =item B<--man>
77              
78             Show full manual.
79              
80             =back
81              
82             =for comment
83             end_standard_fsdb_options
84              
85              
86             =head1 SAMPLE USAGE
87              
88             =head2 Input:
89              
90             #fsdb account passwd uid gid fullname homedir shell
91             johnh * 2274 134 John_Heidemann /home/johnh /bin/bash
92             greg * 2275 134 Greg_Johnson /home/greg /bin/bash
93             root * 0 0 Root /root /bin/bash
94             # this is a simple database
95              
96             =head2 Command:
97              
98             cat DATA/passwd.fsdb | dbrow '_fullname =~ /John/'
99              
100             =head2 Output:
101              
102             #fsdb account passwd uid gid fullname homedir shell
103             johnh * 2274 134 John_Heidemann /home/johnh /bin/bash
104             greg * 2275 134 Greg_Johnson /home/greg /bin/bash
105             # this is a simple database
106             # | /home/johnh/BIN/DB/dbrow
107              
108              
109             =head1 BUGS
110              
111             Doesn't detect references to unknown columns in conditions.
112              
113             END
114             #' for font-lock mode.
115             exit 1;
116              
117             =head1 CLASS FUNCTIONS
118              
119             =cut
120              
121             @ISA = qw(Fsdb::Filter);
122             ($VERSION) = 2.0;
123              
124 1     1   5272 use strict;
  1         2  
  1         37  
125 1     1   4 use Pod::Usage;
  1         2  
  1         135  
126              
127 1     1   5 use Fsdb::Filter;
  1         2  
  1         20  
128 1     1   5 use Fsdb::IO::Reader;
  1         2  
  1         20  
129 1     1   4 use Fsdb::IO::Writer;
  1         1  
  1         706  
130              
131              
132             =head2 new
133              
134             $filter = new Fsdb::Filter::dbrow(@arguments);
135              
136             Create a new dbrow object, taking command-line arguments.
137              
138             =cut
139              
140             sub new ($@) {
141 0     0 1   my $class = shift @_;
142 0           my $self = $class->SUPER::new(@_);
143 0           bless $self, $class;
144 0           $self->set_defaults;
145 0           $self->parse_options(@_);
146 0           $self->SUPER::post_new();
147 0           return $self;
148             }
149              
150              
151             =head2 set_defaults
152              
153             $filter->set_defaults();
154              
155             Internal: set up defaults.
156              
157             =cut
158              
159             sub set_defaults ($) {
160 0     0 1   my($self) = @_;
161 0           $self->SUPER::set_defaults();
162 0           $self->{_invert_match} = undef;
163 0           $self->{_warnings} = undef;
164             }
165              
166             =head2 parse_options
167              
168             $filter->parse_options(@ARGV);
169              
170             Internal: parse command-line arguments.
171              
172             =cut
173              
174             sub parse_options ($@) {
175 0     0 1   my $self = shift @_;
176              
177 0           my(@argv) = @_;
178             $self->get_options(
179             \@argv,
180 0     0     'help|?' => sub { pod2usage(1); },
181 0     0     'man' => sub { pod2usage(-verbose => 2); },
182             'autorun!' => \$self->{_autorun},
183             'close!' => \$self->{_close},
184             'd|debug+' => \$self->{_debug},
185 0     0     'i|input=s' => sub { $self->parse_io_option('input', @_); },
186             'log!' => \$self->{_logprog},
187 0     0     'o|output=s' => sub { $self->parse_io_option('output', @_); },
188             'v|invert-match!' => \$self->{_invert_match},
189             'w|warnings!' => \$self->{_warnings},
190 0 0         ) or pod2usage(2);
191 0           push (@{$self->{_argv}}, @argv);
  0            
192             }
193              
194             =head2 setup
195              
196             $filter->setup();
197              
198             Internal: setup, parse headers.
199              
200             =cut
201              
202             sub setup ($) {
203 0     0 1   my($self) = @_;
204              
205 0           $self->finish_io_option('input', -comment_handler => $self->create_pass_comments_sub);
206 0           my $read_fastpath_sub = $self->{_in}->fastpath_sub();
207              
208 0           $self->finish_io_option('output', -clone => $self->{_in});
209 0           my $write_fastpath_sub = $self->{_out}->fastpath_sub();
210              
211             #
212             # convert code to perl
213             #
214 0           my($partial_code, $needs_lfref) = $self->{_in}->codify(join(") && (", @{$self->{_argv}}));
  0            
215              
216 0 0         my($negate_code) = $self->{_invert_match} ? "!" : "";
217              
218             {
219 0           my $loop_sub;
  0            
220             my $loop_code = q'
221             $loop_sub = sub {
222             my $fref;
223             my $lfref;
224             my $result;
225             while ($fref = &$read_fastpath_sub()) {
226             ' .
227 0 0         ($self->{_warnings} ? "use" : "no") . q' strict "vars";
    0          
228             # BEGIN USER PROVIDED CODE
229             $result = ' . $negate_code . '(' . $partial_code . q');
230              
231             # END USER PROVIDED CODE
232             ' . ($needs_lfref ? q'
233             $lfref = $fref; # save for next pass
234             ' : '') . q'
235             &$write_fastpath_sub($fref) if ($result);
236             };
237             };
238             ';
239 0 0         if ($self->{_debug}) {
240 0           print STDERR "DEBUG:\n$loop_code\n";
241 0           exit 1;
242             };
243 0           eval $loop_code;
244 0 0         $@ && die $self->{_prog} . ": eval error compiling user-provided code: $@.\n";
245 0           $self->{_loop_sub} = $loop_sub;
246             }
247             }
248              
249             =head2 run
250              
251             $filter->run();
252              
253             Internal: run over each rows.
254              
255             =cut
256             sub run ($) {
257 0     0 1   my($self) = @_;
258 0           &{$self->{_loop_sub}}();
  0            
259             }
260              
261              
262             =head1 AUTHOR and COPYRIGHT
263              
264             Copyright (C) 1991-2007 by John Heidemann
265              
266             This program is distributed under terms of the GNU general
267             public license, version 2. See the file COPYING
268             with the distribution for details.
269              
270             =cut
271              
272             1;