File Coverage

blib/lib/DBD/Sys.pm
Criterion Covered Total %
statement 108 142 76.0
branch 5 20 25.0
condition 3 10 30.0
subroutine 28 33 84.8
pod 0 1 0.0
total 144 206 69.9


line stmt bran cond sub pod time code
1 4     4   501453 use DBI ();
  4         30585  
  4         119  
2              
3             package DBD::Sys;
4              
5 4     4   26 use strict;
  4         8  
  4         147  
6 4     4   20 use vars qw(@ISA $VERSION $drh);
  4         12  
  4         289  
7 4     4   26 use base qw(DBI::DBD::SqlEngine);
  4         9  
  4         4607  
8              
9             $VERSION = "0.102";
10              
11             $drh = undef; # holds driver handle(s) once initialised
12              
13             sub driver($;$)
14             {
15 3     3 0 274 my ( $class, $attr ) = @_;
16              
17 3 50       20 $drh->{$class} and return $drh->{$class};
18              
19 3   50     13 $attr ||= {};
20             {
21 4     4   629619 no strict "refs";
  4         11  
  4         589  
  3         14  
22 3   33     31 $attr->{Version} ||= ${ $class . "::VERSION" };
  3         17  
23 3 50       24 $attr->{Name} or ( $attr->{Name} = $class ) =~ s/^DBD\:\://;
24 3   50     22 $attr->{Attribution} ||= 'DBD::Sys by Jens Rehsack';
25             }
26              
27 3         28 $drh = $class->SUPER::driver($attr);
28 3         1966 return $drh;
29             } # driver
30              
31             sub CLONE
32             {
33 0     0   0 undef $drh;
34             } # CLONE
35              
36             package DBD::Sys::dr;
37              
38 4     4   21 use strict;
  4         8  
  4         100  
39 4     4   19 use warnings;
  4         6  
  4         115  
40              
41 4     4   19 use vars qw(@ISA $imp_data_size);
  4         8  
  4         477  
42              
43             @ISA = qw(DBI::DBD::SqlEngine::dr);
44             $DBD::Sys::dr::imp_data_size = 0;
45              
46             sub data_sources
47             {
48 0     0   0 my ( $drh, $attr ) = @_;
49 0         0 my (@list) = ();
50              
51             # You need more sophisticated code than this to set @list...
52 0         0 push( @list, 'dbi:Sys:' );
53              
54             # End of code to set @list
55 0         0 return @list;
56             }
57              
58             package DBD::Sys::db;
59              
60 4     4   21 use strict;
  4         11  
  4         97  
61 4     4   18 use warnings;
  4         6  
  4         122  
62              
63 4     4   17 use vars qw(@ISA $imp_data_size);
  4         14  
  4         184  
64              
65 4     4   53 use Carp qw(croak);
  4         9  
  4         908  
66              
67             require DBD::Sys::PluginManager;
68              
69             @ISA = qw(DBI::DBD::SqlEngine::db);
70             $DBD::Sys::db::imp_data_size = 0;
71              
72             sub set_versions
73             {
74 4     4   30 my $dbh = shift;
75 4         11 $dbh->{sys_version} = $DBD::Sys::VERSION;
76              
77 4         27 return $dbh->SUPER::set_versions();
78             }
79              
80             sub init_valid_attributes
81             {
82 4     4   54 my $dbh = shift;
83              
84 4         25 $dbh->{sys_valid_attrs} = {
85             sys_version => 1, # DBD::Sys version
86             sys_valid_attrs => 1, # DBD::Sys valid attributes
87             sys_readonly_attrs => 1, # DBD::Sys readonly attributes
88             sys_pluginmgr => 1, # DBD::Sys plugin-manager
89             sys_pluginmgr_class => 1, # DBD::Sys plugin-manager class
90             sys_plugin_attrs => 1, # DBD::Sys plugin attributes
91             };
92 4         18 $dbh->{sys_readonly_attrs} = {
93             sys_version => 1, # DBD::File version
94             sys_valid_attrs => 1, # File valid attributes
95             sys_readonly_attrs => 1, # File readonly attributes
96             sys_pluginmgr => 1, # DBD::Sys plugin-manager
97             sys_plugin_attrs => 1, # DBD::Sys plugin attributes
98             };
99              
100 4         12 return $dbh;
101             }
102              
103             sub _load_class
104             {
105 0     0   0 my ( $load_class, $missing_ok ) = @_;
106 4     4   21 no strict 'refs';
  4         9  
  4         2364  
107 0 0       0 return 1 if @{"$load_class\::ISA"}; # already loaded/exists
  0         0  
108 0         0 ( my $module = $load_class ) =~ s!::!/!g;
109 0         0 eval { require "$module.pm"; };
  0         0  
110 0 0       0 return 1 unless $@;
111 0 0 0     0 return 0 if $missing_ok && $@ =~ /^Can't locate \Q$module.pm\E/;
112 0         0 croak $@;
113             }
114              
115             sub init_default_attributes
116             {
117 4     4   2589 my $dbh = shift;
118              
119             # must be done first, because setting flags implicitly calls $dbdname::db->STORE
120 4         33 $dbh->SUPER::init_default_attributes();
121              
122 4         340 $dbh->{sys_pluginmgr_class} = "DBD::Sys::PluginManager";
123 4         28 $dbh->{sys_pluginmgr} = DBD::Sys::PluginManager->new();
124 4         29 $dbh->{sys_plugin_attrs} = $dbh->{sys_pluginmgr}->get_tables_attrs();
125 4         12 foreach my $plugin_attr ( keys %{ $dbh->{sys_plugin_attrs} } )
  4         17  
126             {
127 20         49 $dbh->{sys_valid_attrs}->{$plugin_attr} = 1;
128             }
129              
130 4         29 return $dbh;
131             }
132              
133             sub validate_STORE_attr
134             {
135 5     5   53 my ( $dbh, $attrib, $value ) = @_;
136              
137 5 50       21 $attrib eq "sys_pluginmgr_class" and _load_class( $value, 0 );
138              
139 5         40 return $dbh->SUPER::validate_STORE_attr( $attrib, $value );
140             }
141              
142             sub STORE ($$$)
143             {
144 24     24   822 my ( $dbh, $attrib, $value ) = @_;
145              
146 24         101 $dbh->SUPER::STORE( $attrib, $value );
147              
148 24 50       479 if ( $attrib eq "sys_pluginmgr_class" )
149             {
150 0         0 $@ = undef;
151 0         0 $dbh->{sys_pluginmgr} = $dbh->{sys_pluginmgr_class}->new();
152 0         0 my $sys_plugin_attrs = $dbh->{sys_pluginmgr}->get_tables_attrs();
153              
154 0         0 foreach my $plugin_attr ( keys %{$sys_plugin_attrs} )
  0         0  
155             {
156 0         0 $dbh->{sys_valid_attrs}->{$plugin_attr} = 1;
157             }
158              
159 0         0 foreach my $plugin_attr ( keys %{ $dbh->{sys_plugin_attrs} } )
  0         0  
160             {
161 0 0       0 unless ( exists( $sys_plugin_attrs->{$plugin_attr} ) )
162             {
163 0 0       0 exists $dbh->{$plugin_attr} and delete $dbh->{$plugin_attr};
164 0         0 delete $dbh->{sys_valid_attrs}->{$plugin_attr};
165             }
166             }
167              
168 0         0 $dbh->{sys_plugin_attrs} = $sys_plugin_attrs;
169             }
170              
171 24         84 return $dbh;
172             }
173              
174             sub get_sys_versions
175             {
176 0     0   0 my ( $dbh, $table ) = @_;
177              
178 0         0 my $class = $dbh->{ImplementorClass};
179              
180 0         0 return $dbh->{sys_version}; # sprintf "%s using %s", $dbh->{sys_version}, $dtype;
181             }
182              
183             sub get_avail_tables
184             {
185 0     0   0 my ($dbh) = @_;
186 0         0 my @tables =
187             ( $dbh->SUPER::get_avail_tables(), $dbh->selectrow_array("SELECT * FROM alltables"), );
188 0         0 return @tables;
189             }
190              
191             sub disconnect ($)
192             {
193 3     3   19360 return $_[0]->SUPER::disconnect();
194             }
195              
196             package DBD::Sys::st;
197              
198 4     4   30 use strict;
  4         7  
  4         107  
199 4     4   18 use warnings;
  4         8  
  4         122  
200              
201 4     4   18 use vars qw(@ISA $imp_data_size);
  4         9  
  4         276  
202              
203             @ISA = qw(DBI::DBD::SqlEngine::st);
204             $DBD::Sys::st::imp_data_size = 0;
205              
206             package DBD::Sys::Statement;
207              
208 4     4   18 use strict;
  4         9  
  4         104  
209 4     4   23 use warnings;
  4         11  
  4         112  
210              
211 4     4   16 use vars qw(@ISA);
  4         7  
  4         150  
212              
213 4     4   26 use Scalar::Util qw(weaken);
  4         85  
  4         1246  
214              
215             @ISA = qw(DBI::DBD::SqlEngine::Statement);
216              
217             sub open_table($$$$$)
218             {
219 6     6   30951 my ( $self, $data, $table, $createMode, $lockMode ) = @_;
220              
221 6         23 my $attr_prefix = 'sys_' . lc($table) . '_';
222 6         13 my $attrs = {};
223 6         12 my $meta = {};
224 6         14 my $dbh = $data->{Database};
225 6         8 foreach my $attr ( keys %{$dbh} )
  6         64  
226             {
227 210 50       627 next unless ( $attr =~ m/^$attr_prefix(.+)$/ );
228 0         0 $meta->{$1} = $dbh->{$attr};
229             }
230 6         28 $attrs->{meta} = $meta;
231 6         13 $attrs->{database} = $dbh;
232 6         17 $attrs->{owner} = $self;
233 6         21 weaken( $attrs->{owner} );
234 6         15 weaken( $attrs->{database} );
235              
236 6         38 my $tbl = $dbh->{sys_pluginmgr}->get_table( $table, $attrs );
237              
238 0           return $tbl;
239             }
240              
241             #################### main pod documentation start ###################
242              
243             =head1 NAME
244              
245             DBD::Sys - System tables interface via DBI
246              
247             =head1 SYNOPSIS
248              
249             use DBI;
250             my $dbh = DBI->connect('DBI::Sys:');
251             my $st = $dbh->prepare('select distinct * from filesystems join filesysdf on mountpoint');
252             my $num = $st->execute();
253             if( $num > 0 )
254             {
255             while( my $row = $st->fetchrow_hashref() )
256             {
257             # ...
258             }
259             }
260              
261             =head1 DESCRIPTION
262              
263             DBD::Sys is a so called database driver for L designed to request
264             information from system tables using SQL. It's based on L as
265             SQL engine and allows to be extended by L.
266              
267             =head2 Prerequisites
268              
269             Of course, a DBD requires L to run. Further, L as SQL
270             engine is required, L to manage the plugin's and
271             L for installation. Finally, to speed up some checks,
272             L is needed.
273              
274             All these modules are mandatory and DBD::Sys will fail when they are not
275             available.
276              
277             To request system information, existing modules from CPAN are used - there
278             are available ones to provide access to some system tables. These modules are
279             optional, but recommended. It wouldn't make much sense to use DBD::Sys without
280             the ability to access the tables from the (operating) system.
281              
282             To get an overview which dependencies are there, please check the plugins
283             or take a look into META.yml.
284              
285             =head1 USAGE
286              
287             =head2 Installation
288              
289             We chose C installation, because not every system has a
290             suitable make utility - but at least everyone who's using perl modules has
291             a running perl. So installing can be done after extracting
292              
293             gzip -dc DBD-Sys-${VERSION}.tar.gz | tar xvf -
294              
295             without too much extra effort:
296              
297             1 cd DBD-Sys-${VERSION}
298             2 perl Build.PL
299             3 ./Build
300             4 ./Build test
301             5 ./Build install
302              
303             If you want to skip the tests (not recommended), you can skip over lines 3
304             and 4.
305              
306             =head2 Fetching data
307              
308             To retrieve data, you can use the following example:
309              
310             my $dbh = DBI->connect('DBI:Sys:');
311             $st = $dbh->prepare( 'SELECT DISTINCT username, uid FROM pwent WHERE username=?' );
312             $num = $st->execute(getlogin() || $ENV{USER} || $ENV{USERNAME});
313             while( $row = $st->fetchrow_hashref() )
314             {
315             printf( "Found result row: uid = %d, username = %s\n", $row->{uid}, $row->{username} );
316             }
317              
318             =head2 Error handling
319              
320             Errors while processing statements are handled via DBI - read L
321             documentation, especially the C and C documentation,
322             if you're not familiar with error handling in DBI.
323              
324             Errors while modifying attributes, calling driver methods etc. are
325             reported by throwing an exception using L.
326              
327             =head2 Metadata
328              
329             Each table implementor can request configurable meta data attributes.
330             They will be accessible via the database handle:
331              
332             print $dbh->{"sys_" . lc $table . "_" . $attr}, "\n";
333             # e.g.
334             print DBI->neat( $dbh->{sys_filesysdf_blocksize} ), "\n";
335              
336             =head1 BUGS & LIMITATIONS
337              
338             This module does not support any changes to the provided tables in order
339             to prevent inconsistent data.
340              
341             The design of the plugins makes it less predictable what columns are
342             provided in the end. Well, at least those columns from the tables
343             provided by the DBD::Sys::Plugin::Meta and DBD::Sys::Plugin::Any
344             will be available, even if they are not filled with data when the
345             appropriate module is missing (e.g. if L is not
346             available, the table C gets the columns provided by
347             L, but no data at all).
348              
349             All additional table implementors must use the same primary key as
350             all other implementors. To stay at the example of C, the
351             primary key is I - and if any additional module provides
352             another implementation (with data from another module than
353             C), it needs to ensure that the column I
354             is provided and unique. Additionally it must return I as
355             primary key when it's method C is invoked.
356              
357             =head1 AUTHOR
358              
359             Jens Rehsack Alexander Breibach
360             CPAN ID: REHSACK
361             rehsack@cpan.org alexander.breibach@googlemail.com
362             http://search.cpan.org/~rehsack/
363              
364             =head1 COPYRIGHT
365              
366             This program is free software; you can redistribute
367             it and/or modify it under the same terms as Perl itself.
368              
369             The full text of the license can be found in the
370             LICENSE file included with this module.
371              
372             =head1 SUPPORT
373              
374             Free support can be requested via regular CPAN bug-tracking system at
375             L. There is
376             no guaranteed reaction time or solution time, but it's always tried to give
377             accept or reject a reported ticket within a week. It depends on business load.
378             That doesn't mean that ticket via rt aren't handles as soon as possible,
379             that means that soon depends on how much I have to do.
380              
381             Business and commercial support should be acquired from the authors via
382             preferred freelancer agencies.
383              
384             =head1 SEE ALSO
385              
386             perl(1), L, L, L, L,
387             L.
388              
389             =cut
390              
391             #################### main pod documentation end ###################
392              
393             1;