File Coverage

blib/lib/DBD/AnyData2.pm
Criterion Covered Total %
statement 42 141 29.7
branch 0 44 0.0
condition 0 33 0.0
subroutine 14 34 41.1
pod 0 1 0.0
total 56 253 22.1


line stmt bran cond sub pod time code
1             #######################################################################
2             #
3             # DBD::AnyData2 - a DBI driver for AnyData2 files
4             #
5             # Copyright (c) 2015 by Jens Rehsack
6             #
7             # All rights reserved.
8             #
9             # You may freely distribute and/or modify this module under the terms
10             # of either the GNU General Public License (GPL) or the Artistic License,
11             # as specified in the Perl README file.
12             #
13             # USERS - see the pod at the bottom of this file
14             #
15             # DBD AUTHORS - see the comments in the code
16             #
17             #######################################################################
18             require 5.008;
19 1     1   14546 use strict;
  1         2  
  1         25  
20 1     1   4 use warnings;
  1         1  
  1         59  
21              
22             #################
23             package DBD::AnyData2;
24             #################
25 1     1   5 use base qw(DBI::DBD::SqlEngine);
  1         5  
  1         623  
26 1     1   146251 use vars qw($VERSION $ATTRIBUTION $drh $methods_already_installed);
  1         2  
  1         96  
27             $VERSION = '0.001';
28             $ATTRIBUTION = 'DBD::AnyData2 by Jens Rehsack';
29              
30 1     1   422 use AnyData2;
  1         312  
  1         114  
31              
32             # no need to have driver() unless you need private methods
33             #
34             sub driver ($;$)
35             {
36 0     0 0   my ( $class, $attr ) = @_;
37 0 0         return $drh if ($drh);
38              
39             # do the real work in DBI::DBD::SqlEngine
40             #
41 0           $attr->{Attribution} = 'DBD::AnyData2 by Jens Rehsack';
42 0           $drh = $class->SUPER::driver($attr);
43              
44             # install private methods
45             #
46             # this requires that ad2_ (or foo_) be a registered prefix
47             # but you can write private methods before official registration
48             # by hacking the $dbd_prefix_registry in a private copy of DBI.pm
49             #
50             #unless ( $methods_already_installed++ )
51             #{
52             # DBD::AnyData2::st->install_method('ad2_schema');
53             #}
54              
55 0           return $drh;
56             }
57              
58             sub CLONE
59             {
60 0     0     undef $drh;
61             }
62              
63             #####################
64             package DBD::AnyData2::dr;
65             #####################
66             $DBD::AnyData2::dr::imp_data_size = 0;
67             @DBD::AnyData2::dr::ISA = qw(DBI::DBD::SqlEngine::dr);
68              
69             # you could put some :dr private methods here
70              
71             # you may need to over-ride some DBI::DBD::SqlEngine::dr methods here
72             # but you can probably get away with just letting it do the work
73             # in most cases
74              
75             #####################
76             package DBD::AnyData2::db;
77             #####################
78             $DBD::AnyData2::db::imp_data_size = 0;
79             @DBD::AnyData2::db::ISA = qw(DBI::DBD::SqlEngine::db);
80              
81 1     1   5 use Carp qw/carp/;
  1         1  
  1         263  
82              
83             sub set_versions
84             {
85 0     0     my $this = $_[0];
86 0           $this->{ad2_version} = $DBD::AnyData2::VERSION;
87 0           return $this->SUPER::set_versions();
88             }
89              
90             sub init_valid_attributes
91             {
92 0     0     my $dbh = shift;
93              
94             # define valid private attributes
95             #
96             # attempts to set non-valid attrs in connect() or
97             # with $dbh->{attr} will throw errors
98             #
99             # the attrs here *must* start with ad2_ or foo_
100             #
101             # see the STORE methods below for how to check these attrs
102             #
103             $dbh->{ad2_valid_attrs} = {
104 0           ad2_version => 1, # verbose DBD::AnyData2 version
105             ad2_valid_attrs => 1, # DBD::AnyData2::db valid attrs
106             ad2_readonly_attrs => 1, # DBD::AnyData2::db r/o attrs
107             ad2_storage_type => 1, # default storage type unless specified per table
108             ad2_storage_attrs => 1, # default storage attrs unless specified per table
109             ad2_format_type => 1, # default format type unless specified per table
110             ad2_format_attrs => 1, # default format attrs unless specified per table
111             ad2_meta => 1, # DBD::AnyData2 public access for f_meta
112             ad2_tables => 1, # DBD::AnyData2 public access for f_meta
113             };
114             $dbh->{ad2_readonly_attrs} = {
115 0           ad2_version => 1, # verbose DBD::AnyData2 version
116             ad2_valid_attrs => 1, # DBD::AnyData2::db valid attrs
117             ad2_readonly_attrs => 1, # DBD::AnyData2::db r/o attrs
118             ad2_meta => 1, # DBD::AnyData2 public access for f_meta
119             };
120              
121 0           $dbh->{ad2_meta} = "ad2_tables";
122              
123 0           return $dbh->SUPER::init_valid_attributes();
124             }
125              
126             sub init_default_attributes
127             {
128 0     0     my ( $dbh, $phase ) = @_;
129              
130 0           $dbh->SUPER::init_default_attributes($phase);
131 0           $dbh->{ad2_storage_type} = 'File::Blockwise';
132 0           $dbh->{ad2_format_type} = 'Fixed';
133              
134 0           return $dbh;
135             }
136              
137             sub get_ad2_versions
138             {
139 0     0     my ( $dbh, $table ) = @_;
140 0   0       $table ||= '';
141              
142 0           my $meta;
143 0           my $class = $dbh->{ImplementorClass};
144 0           $class =~ s/::db$/::Table/;
145 0 0         $table and ( undef, $meta ) = $class->get_table_meta( $dbh, $table, 1 );
146 0 0 0       $meta or ( $meta = {} and $class->bootstrap_table_meta( $dbh, $meta, $table ) );
147              
148 0           return sprintf( "%s using %s", $dbh->{ad2_version}, $AnyData2::VERSION );
149             }
150              
151             package DBD::AnyData2::st;
152              
153 1     1   5 use strict;
  1         1  
  1         15  
154 1     1   3 use warnings;
  1         1  
  1         46  
155              
156             our $imp_data_size = 0;
157             our @ISA = qw(DBI::DBD::SqlEngine::st);
158              
159             # ====== DataSource ============================================================
160              
161             package DBD::AnyData2::DataSource;
162              
163 1     1   3 use strict;
  1         1  
  1         18  
164 1     1   2 use warnings;
  1         1  
  1         28  
165              
166 1     1   3 use Carp;
  1         1  
  1         143  
167              
168             @DBD::AnyData2::DataSource::ISA = "DBI::DBD::SqlEngine::DataSource";
169              
170             sub complete_table_name ($$;$)
171             {
172 0     0     my ( $self, $meta, $table, $respect_case ) = @_;
173 0           $table;
174             }
175              
176             sub open_data ($)
177             {
178 0     0     my ( $self, $meta, $attrs, $flags ) = @_;
179 0           $meta->{ad2h} = AnyData2->new( @$meta{qw(ad2_format_type ad2_format_attrs ad2_storage_type ad2_storage_attrs)} );
180 0 0         defined $meta->{col_names} or $meta->{col_names} = $meta->{ad2h}->cols;
181             }
182              
183             ############################
184             package DBD::AnyData2::Statement;
185             ############################
186              
187             @DBD::AnyData2::Statement::ISA = qw(DBI::DBD::SqlEngine::Statement);
188              
189             ########################
190             package DBD::AnyData2::Table;
191             ########################
192              
193 1     1   3 use Carp qw/croak/;
  1         1  
  1         36  
194 1     1   3 use Module::Runtime qw(require_module);
  1         1  
  1         3  
195              
196             @DBD::AnyData2::Table::ISA = qw(DBI::DBD::SqlEngine::Table);
197              
198             my %reset_on_modify = (
199             ad2_storage_type => ["ad2_storage_attrs"],
200             ad2_format_type => ["ad2_format_type"],
201             );
202              
203             __PACKAGE__->register_reset_on_modify( \%reset_on_modify );
204              
205             sub bootstrap_table_meta
206             {
207 0     0     my ( $self, $dbh, $meta, $table ) = @_;
208              
209 0   0       $meta->{ad2_storage_type} ||= $dbh->{ad2_storage_type} || 'FileSystem';
      0        
210 0   0       $meta->{ad2_storage_attrs} ||= $dbh->{ad2_storage_attrs} || {};
      0        
211 0   0       $meta->{ad2_format_type} ||= $dbh->{ad2_format_type} || 'FileSystem';
      0        
212 0   0       $meta->{ad2_format_attrs} ||= $dbh->{ad2_format_attrs} || {};
      0        
213              
214 0 0         $meta->{sql_data_source} or $meta->{sql_data_source} = "DBD::AnyData2::DataSource";
215              
216 0           my $ad2_ft = $meta->{ad2_format_type};
217 0 0         $ad2_ft =~ m/^AnyData2::Format::/ or $ad2_ft = "AnyData2::Format::${ad2_ft}";
218 0           eval {
219 0           require_module($ad2_ft);
220             $ad2_ft->isa("AnyData2::Role::AdvancedChanging")
221 0 0 0       and $meta->{sql_table_class} ||= "DBD::AnyData2::AdvancedChangingTable";
222             };
223              
224 0           $self->SUPER::bootstrap_table_meta( $dbh, $meta, $table );
225             }
226              
227             sub drop ($$)
228             {
229 0     0     my ( $self, $data ) = @_;
230 0           my $meta = $self->{meta};
231 0           $meta->{ad2h}->drop;
232             }
233              
234             #sub init_table_meta
235             #{
236             # my ( $self, $dbh, $meta, $table ) = @_;
237             #
238             # $self->SUPER::init_table_meta( $dbh, $meta, $table );
239             #}
240              
241             sub fetch_row
242             {
243 0     0     my ( $self, $data ) = @_;
244 0           my $meta = $self->{meta};
245              
246 0           my $fields;
247 0           eval { $fields = $meta->{ad2h}->fetchrow; };
  0            
248 0 0         $@ and croak $@; # XXX kind-of diag
249 0 0         $fields or return; # XXX eof signalling?
250 0 0         $self->{row} = (@$fields ? $fields : undef);
251             }
252              
253             sub push_row
254             {
255 0     0     my ( $self, $data, $fields ) = @_;
256 0           my $meta = $self->{meta};
257 0           $meta->{ad2h}->pushrow($fields);
258             }
259              
260             sub seek ($$$$)
261             {
262 0     0     my ( $self, $data, $pos, $whence ) = @_;
263 0           my $meta = $self->{meta};
264 0           $meta->{ad2h}->seek( $pos, $whence );
265             }
266              
267             sub truncate ($$)
268             {
269 0     0     my ( $self, $data ) = @_;
270 0           my $meta = $self->{meta};
271 0           $meta->{ad2h}->truncate;
272 0           1;
273             }
274              
275             # you may not need to explicitly DESTROY the ::Table
276             # put cleanup code to run when the execute is done
277             #
278             sub DESTROY ($)
279             {
280 0     0     my $self = shift;
281 0           my $meta = $self->{meta};
282 0 0         $meta->{ad2h} and undef $meta->{ad2h};
283              
284 0           $self->SUPER::DESTROY();
285             }
286              
287             ########################
288             package DBD::AnyData2::AdvancedChangingTable;
289             ########################
290              
291             @DBD::AnyData2::AdvancedChangingTable::ISA = qw(DBD::AnyData2::Table);
292              
293 1     1   431 use Carp qw/croak/;
  1         2  
  1         418  
294              
295             sub capability($)
296             {
297 0     0     my ( $self, $capname ) = @_;
298 0 0         exists $self->{capabilities}->{$capname} and return $self->{capabilities}->{$capname};
299              
300 0           my $meta = $self->{meta};
301              
302             $capname eq "insert_new_row"
303 0 0         and $self->{capabilities}->{insert_new_row} = $meta->{ad2h}->can("insert_new_row");
304             $capname eq "delete_one_row"
305 0 0         and $self->{capabilities}->{delete_one_row} = $meta->{ad2h}->can("delete_one_row");
306             $capname eq "delete_current_row"
307             and $self->{capabilities}->{delete_current_row} =
308 0 0 0       ( $meta->{ad2h}->can("delete_current_row") and $meta->{ad2h}->capability("inplace_delete") );
309             $capname eq "update_one_row"
310 0 0         and $self->{capabilities}->{update_one_row} = $meta->{ad2h}->can("update_one_row");
311             $capname eq "update_current_row"
312             and $self->{capabilities}->{update_current_row} =
313 0 0 0       ( $meta->{ad2h}->can("update_current_row") and $meta->{ad2h}->capability("inplace_update") );
314             $capname eq "update_specific_row"
315 0 0         and $self->{capabilities}->{update_specific_row} = $meta->{ad2h}->can("update_specific_row");
316              
317 0           $self->SUPER::capability($capname);
318             }
319              
320             # you must define push_row except insert_new_row and update_specific_row is defined
321             # it is called on inserts and updates as primitive
322             #
323             sub insert_new_row ($$$)
324             {
325 0     0     my ( $self, $data, $row_aryref ) = @_;
326 0           my $meta = $self->{meta};
327 0           my $ncols = scalar( @{ $meta->{col_names} } );
  0            
328 0           my $nitems = scalar( @{$row_aryref} );
  0            
329 0 0         $ncols == $nitems
330             or croak "You tried to insert $nitems, but table is created with $ncols columns";
331              
332 0           $meta->{ad2h}->insert_new_row($row_aryref);
333             }
334              
335             sub delete_one_row ($$$)
336             {
337 0     0     my ( $self, $data, $aryref ) = @_;
338 0           my $meta = $self->{meta};
339 0           $meta->{ad2h}->delete_one_row($aryref);
340             }
341              
342             sub update_one_row ($$$)
343             {
344 0     0     my ( $self, $data, $aryref ) = @_;
345 0           my $meta = $self->{meta};
346             # we don't know the key item
347 0           $meta->{ad2h}->update_one_row($aryref);
348             }
349              
350             sub update_specific_row ($$$$)
351             {
352 0     0     my ( $self, $data, $aryref, $origary ) = @_;
353 0           my $meta = $self->{meta};
354 0 0         return unless ( defined $origary->[0] );
355 0 0         $origary->[0] eq $aryref->[0] or croak "Updating a row with new transaction ID is not supported. DELETE and INSERT instead.";
356 0 0         my $row = ( ref($aryref) eq 'ARRAY' ) ? $aryref : [$aryref];
357 0           $meta->{ad2h}->update_specific_row($aryref, $origary);
358             }
359              
360             1;
361             __END__