File Coverage

blib/lib/DBD/AnyData.pm
Criterion Covered Total %
statement 146 330 44.2
branch 27 108 25.0
condition 15 58 25.8
subroutine 31 48 64.5
pod 0 1 0.0
total 219 545 40.1


in the first
line stmt bran cond sub pod time code
1             #########################################################################
2             # DBD::AnyData - a DBI driver for files and data structures
3             #
4             # This module is copyright (c), 2001 by Jeff Zucker
5             # All rights reserved.
6             #
7             # This is free software. You may distribute it under
8             # the same terms as Perl itself as specified in the
9             # Perl README file.
10             #
11             # WARNING: no warranty of any kind is implied.
12             #
13             # To learn more: enter "perldoc DBD::AnyData" at the command prompt,
14             # or search in this file for =head1 and read the text below it
15             #
16             #########################################################################
17              
18             package DBD::AnyData;
19              
20 2     2   91594 use strict;
  2         6  
  2         82  
21 2     2   45 use warnings;
  2         5  
  2         366  
22              
23 2     2   7468 use AnyData;
  2         25507  
  2         248  
24             require DBI::DBD::SqlEngine;
25 2     2   19 use base qw(DBI::DBD::SqlEngine);
  2         3  
  2         3590  
26             require SQL::Statement;
27             require SQL::Eval;
28              
29 2     2   596722 use vars qw($VERSION $err $errstr $sqlstate $drh $methods_already_installed);
  2         4  
  2         534  
30              
31             $VERSION = '0.110';
32              
33             $err = 0; # holds error code for DBI::err
34             $errstr = ""; # holds error string for DBI::errstr
35             $sqlstate = ""; # holds SQL state for DBI::state
36             $drh = undef; # holds driver handle once initialized
37              
38             sub driver
39             {
40 1     1 0 1352 my ( $class, $attr ) = @_;
41 1 50       5 return $drh if $drh; # already created - return same one
42 1         17 $drh = $class->SUPER::driver(
43             {
44             'Name' => 'AnyData',
45             'Version' => $VERSION,
46             'Err' => \$DBD::AnyData::err,
47             'Errstr' => \$DBD::AnyData::errstr,
48             'State' => \$DBD::AnyData::sqlstate,
49             'Attribution' => 'DBD::AnyData by Jens Rehsack',
50             }
51             );
52              
53 1 50       550 unless ( $methods_already_installed++ )
54             {
55 1         4 DBD::AnyData::db->install_method('ad_import');
56 1         25 DBD::AnyData::db->install_method('ad_catalog');
57 1         26 DBD::AnyData::db->install_method('ad_convert');
58 1         24 DBD::AnyData::db->install_method('ad_export');
59 1         24 DBD::AnyData::db->install_method('ad_clear');
60 1         24 DBD::AnyData::db->install_method('ad_dump');
61             }
62              
63 1         33 return $drh;
64             }
65              
66             sub CLONE
67             {
68 0     0   0 undef $drh;
69             }
70              
71             package DBD::AnyData::dr; # ====== DRIVER ======
72              
73 2     2   11 use strict;
  2         3  
  2         68  
74 2     2   10 use warnings;
  2         4  
  2         68  
75              
76 2     2   11 use vars qw($imp_data_size);
  2         4  
  2         194  
77              
78             $DBD::AnyData::dr::imp_data_size = 0;
79             @DBD::AnyData::dr::ISA = qw(DBI::DBD::SqlEngine::dr);
80              
81             sub disconnect_all
82             {
83 1     1   325 shift->{ad_tables} = {};
84             }
85              
86             sub DESTROY
87             {
88 0     0   0 shift->{ad_tables} = {};
89             }
90              
91             package DBD::AnyData::db; # ====== DATABASE ======
92              
93 2     2   11 use strict;
  2         2  
  2         70  
94 2     2   10 use warnings;
  2         2  
  2         52  
95              
96 2     2   8 use vars qw($imp_data_size);
  2         9  
  2         5069  
97              
98             require Cwd;
99             require File::Spec;
100              
101             $DBD::AnyData::db::imp_data_size = 0;
102             @DBD::AnyData::db::ISA = qw(DBI::DBD::SqlEngine::db);
103              
104             sub init_default_attributes
105             {
106 1     1   123 my $dbh = shift;
107              
108             # must be done first, because setting flags implicitly calls $dbdname::db->STORE
109 1         8 $dbh->SUPER::init_default_attributes();
110              
111 1         82 $dbh->{f_dir} = Cwd::abs_path( File::Spec->curdir() );
112              
113 1         3 return $dbh;
114             }
115              
116             sub set_versions
117             {
118 1     1   56 my $this = $_[0];
119 1         4 $this->{ad_version} = $DBD::AnyData::VERSION;
120 1         7 return $this->SUPER::set_versions();
121             }
122              
123             sub disconnect
124             {
125 0     0   0 my $dbh = $_[0];
126 0         0 $dbh->SUPER::disconnect();
127 0         0 $dbh->{ad_tables} = {};
128 0         0 $dbh->STORE( 'Active', 0 );
129 0         0 return 1;
130             }
131              
132             sub validate_STORE_attr
133             {
134 2     2   258 my ( $dbh, $attrib, $value ) = @_;
135              
136 2 100       9 if ( $attrib eq "f_dir" )
137             {
138 1 50       33 -d $value
139             or return $dbh->set_err( $DBI::stderr, "No such directory '$value'" );
140 1 50       9 File::Spec->file_name_is_absolute($value)
141             or $value = Cwd::abs_path($value);
142             }
143              
144 2         11 return $dbh->SUPER::validate_STORE_attr( $attrib, $value );
145             }
146              
147             sub get_ad_versions
148             {
149 0     0   0 my ( $dbh, $table ) = @_;
150              
151 0         0 my $dver;
152             my $eval_str;
153 0         0 $eval_str = sprintf( '$dver = $%s::VERSION', "AnyData" );
154 0         0 eval $eval_str;
155 0         0 my $dtype = "AnyData";
156 0 0       0 $dtype .= ' (' . $dver . ')' if $dver;
157              
158 0         0 return sprintf( "%s using %s", $dbh->{ad_version}, $dtype );
159             }
160             #
161             # DRIVER PRIVATE METHODS
162             #
163              
164             sub ad_mod_catalog
165             {
166 0     0   0 my ( $self, $tname, $key, $value ) = @_;
167 0         0 $self->{ad_tables}->{$tname}->{$key} = $value;
168             }
169              
170             sub ad_clear
171             {
172 1     1   2511 my $self = shift;
173 1         4 my $tname = shift;
174 1 50 33     10 if ( $tname eq 'all' or $tname eq '' )
175             {
176 0         0 $self->{ad_tables} = {};
177             }
178             else
179             {
180 1         6 delete $self->{ad_tables}->{$tname};
181             }
182             }
183              
184             sub ad_get_catalog
185             {
186 8     8   14 my $self = shift;
187 8         11 my $tname = shift;
188             #################################################################
189             # Patch from Wes Hardaker
190             #################################################################
191 8 50       25 if ($tname)
192             {
193 8 100       43 return $self->{ad_tables}->{$tname}
194             if ( $self->{ad_tables}->{$tname} );
195 1         4 return $self->{ad_tables}->{__default};
196             }
197             #################################################################
198 0         0 return $self->{ad_tables};
199             }
200              
201             sub ad_export
202             {
203 0     0   0 my $dbh = shift;
204 0         0 my $table_name = shift;
205 0         0 my $format = shift;
206 0         0 my $file_name = shift;
207 0         0 my $flags = shift;
208 0         0 my $data;
209 0         0 my $catalog = $dbh->func( $table_name, 'ad_get_catalog' );
210             #use Data::Dumper; print Dumper $catalog;
211 0 0 0     0 if ( $catalog->{format} && 'XML HTMLtable' =~ /$catalog->{format}/ )
212             {
213             #use Data::Dumper; print "!",Dumper $catalog; exit;
214 0 0       0 my $sth = $dbh->prepare("SELECT 1 FROM $table_name") or die DBI->errstr;
215 0         0 $sth->execute; # or die DBI->errstr;
216             ###z return $catalog->{ad}->export($format,$file_name,$flags) if 'XML HTMLtable' =~ /$format/;
217 0 0       0 return $catalog->{ad}->export( $file_name, $flags ) if 'XML HTMLtable' =~ /$format/;
218 0         0 $data = $dbh->selectall_arrayref("SELECT * FROM $table_name");
219             #my $sth = $dbh->prepare("SELECT * FROM $table_name");
220             #$sth->execute;
221             #unshift @$data, $sth->{NAME};
222             }
223             else
224             {
225             #z $data = $dbh->func($table_name,'ad_get_catalog')->{records};
226 0         0 my $sth = $dbh->prepare("SELECT * FROM $table_name WHERE 1=0");
227 0         0 $sth->execute;
228 0         0 $data = $catalog->{ad}->{storage}->{records};
229             }
230 0 0       0 $data = $dbh->selectall_arrayref("SELECT * FROM $table_name")
231             if $format =~ /XML|HTMLtable/;
232             #use Data::Dumper;
233             #die Dumper $data;
234             # print Dumper $dbh->func( $table_name,'ad_get_catalog');
235              
236 0         0 my $newcols = $dbh->func( $table_name, 'ad_get_catalog' )->{ad}->{storage}->{col_names};
237 0 0       0 unshift @$data, $newcols if $newcols;
238 0         0 return AnyData::adConvert( 'Base', $data, $format, $file_name, undef, $flags );
239             # return AnyData::adExport({},$format,$data,$file_name,undef,$flags);
240             }
241              
242             sub ad_convert
243             {
244 0     0   0 my $dbh = shift;
245 0         0 my $format = shift;
246 0 0       0 if ( $format eq 'DBI' )
247             {
248 0         0 my $data = shift;
249 0         0 my $newformat = shift;
250 0 0 0     0 die "table_name required to convert DBI"
251             unless $_[1] and $_[1]->{table_name};
252 0         0 my $table_name = $_[1]->{table_name};
253 0         0 $dbh->func( $table_name, 'DBI', $data, 'ad_import' );
254 0         0 my $rv = $dbh->func( $table_name, $newformat, 'ad_export' );
255 0         0 $dbh->func( $table_name, 'ad_clear' );
256 0         0 return $rv;
257             }
258 0         0 return AnyData::adConvert( $format, @_ );
259             }
260              
261             sub ad_import
262             {
263 1     1   10 my $dbh = shift;
264 1         3 my ( $table_name, $format, $file_name, $flags ) = @_;
265 1 50       4 $format = 'CSV' if $format eq 'ARRAY';
266 1         6 my $old_catalog = $dbh->func( $table_name, 'ad_get_catalog' );
267 1         3 my $old_columns;
268             my $old_records;
269 1 50       4 if ($old_catalog)
270             {
271 0         0 my $sth = $dbh->prepare("SELECT * FROM $table_name");
272 0         0 $sth->execute;
273 0         0 $old_records = $sth->fetchall_arrayref;
274 0         0 $old_columns = $sth->{NAME};
275             }
276 1   33     7 my $sql = $flags->{sql} || "SELECT * FROM $table_name";
277             # die $sql;
278 1   33     8 my @params = $flags->{params} || ();
279 1 50       23 if ( 'XML HTMLtable' =~ /$format/ )
    50          
280             {
281 0         0 $dbh->func( $table_name, $format, $file_name, $flags, 'ad_catalog' );
282 0         0 my $sth = $dbh->prepare("SELECT * FROM $table_name WHERE 1=0");
283 0         0 $sth->execute;
284 0         0 $sth->finish;
285 0 0       0 return unless $old_catalog;
286             }
287             elsif ( ref($file_name) )
288             {
289 0         0 $flags->{recs} = $file_name;
290 0         0 $flags->{storage} = 'RAM';
291             #$flags->{col_names} =$old_columns if $old_columns;
292 0         0 $dbh->func( $table_name, $format, '', $flags, 'ad_catalog' );
293             }
294             else
295             {
296 1         7 $dbh->func( $table_name, $format, $file_name, $flags, 'ad_catalog' );
297             #$dbh->func(@_,'ad_catalog');
298             }
299 1         4 my $dbh2 = $dbh;
300 1 50       5 $dbh2 = $file_name if $format eq 'DBI';
301 1 50       8 my $sth = $dbh2->prepare($sql) or die DBI->errstr;
302             # die "$sql";
303 1 50       826 $sth->execute(@params) or die DBI->errstr;
304 0 0       0 my $cols = $sth->{NAME} or die DBI->errstr;
305             # die @$cols;
306 0         0 my $records;
307 0 0       0 if ($old_records)
308             {
309 0         0 my $colstr = join ',', @$old_columns;
310 0         0 my $cr = join " TEXT,", @$old_columns;
311 0         0 $cr = "CREATE TABLE temp__ ($cr TEXT)";
312 0 0       0 $dbh->do($cr) or die DBI->errstr;
313 0         0 while ( my $row = $sth->fetchrow_hashref )
314             {
315 0         0 my $old_row;
316 0 0       0 if ( $flags->{lookup_key} )
317             {
318 0   0     0 my $lookup = $flags->{lookup_key} || $sth->{NAME}->[0];
319 0   0     0 my $val = $row->{$lookup} || next;
320 0         0 my $oldsth = $dbh->prepare(
321             qq{
322             SELECT * FROM temp__ WHERE $lookup = '$val'
323             }
324             );
325 0         0 $oldsth->execute;
326 0         0 $old_row = $oldsth->fetchrow_hashref;
327 0         0 my @tmp = $dbh->selectrow_array("SELECT * FROM temp__ WHERE $lookup = $val");
328 0         0 my $dup;
329              
330 0         0 for my $x (@tmp)
331             {
332 0 0       0 if ( !defined $x )
333             {
334 0         0 $dup++;
335 0         0 last;
336             }
337             }
338 0 0       0 if ($dup)
339             {
340             #print "@tmp";
341 0 0       0 $dbh->do("DELETE FROM temp__ WHERE $lookup = $val")
342             or die DBI->errstr;
343             }
344             }
345 0         0 my @params;
346 0         0 for (@$old_columns)
347             {
348 0         0 my $newval = $row->{$_};
349 0   0     0 $newval ||= $old_row->{$_};
350 0         0 push @params, $newval;
351             }
352 0         0 my $paramStr = ( join ",", ("?") x @$old_columns );
353 0         0 my $ins_sql = "INSERT INTO temp__ ($colstr) VALUES ($paramStr)";
354 0 0       0 $dbh->do( $ins_sql, undef, @params ) or die DBI->errstr;
355             }
356 0   0     0 $records ||= $dbh->selectall_arrayref($sql);
357             }
358             else
359             {
360 0         0 $records = $sth->fetchall_arrayref;
361             }
362 0 0       0 $cols = $old_columns if $old_columns;
363 0 0       0 unshift @$records, $cols unless $flags->{col_names};
364 0 0 0     0 $dbh2->disconnect if $format eq 'DBI' and !$flags->{keep_connection};
365 0 0       0 $file_name = '' if ref($file_name) eq 'ARRAY';
366 0         0 delete $flags->{recs};
367 0         0 delete $flags->{storage};
368 0         0 delete $flags->{format};
369             #$flags = {} if 'XML HTMLtable' =~ /$format/;
370 0 0       0 if ( 'XML HTMLtable' =~ /$format/ )
371             {
372 0         0 delete $flags->{ad};
373 0         0 $flags->{file_name} = '';
374             }
375             # use Data::Dumper; print Dumper $flags;
376 0   0     0 $flags->{records} ||= $records;
377 0         0 $dbh->func( $table_name, 'ad_clear' );
378 0         0 $dbh->func( $table_name, 'Base', $file_name, $flags, 'ad_catalog' );
379 0         0 my $firstrow = {};
380 0 0       0 return unless $records->[1];
381 0         0 @{$firstrow}{@$cols} = @{ $records->[1] };
  0         0  
  0         0  
382 0         0 return $firstrow;
383             }
384              
385             sub ad_catalog
386             {
387 2     2   503 my $dbh = shift;
388 2         6 my @specs = @_;
389 2 50       9 my $table_info =
390             ( ref $specs[0] ) eq 'ARRAY'
391             ? shift @specs
392             : [ \@specs ];
393 2         3 for my $one_table ( @{$table_info} )
  2         5  
394             {
395 2         2 my ( $table_name, $format, $file_name, $flags );
396 2 50       8 if ( ref $one_table eq 'ARRAY' )
397             {
398 2         3 ( $table_name, $format, $file_name, $flags ) = @{$one_table};
  2         5  
399 2 50       5 $flags = {} unless $flags;
400 2         5 $flags->{table_name} = $table_name;
401 2 50       5 if ( ref $format eq 'HASH' )
402             {
403 0         0 $flags->{data} = $format->{data};
404 0         0 $format = 'Base';
405             }
406 2         4 $flags->{format} = $format;
407 2         4 $flags->{file_name} = $file_name;
408             }
409 2 50       13 if ( ref $one_table eq 'HASH' )
410             {
411 0         0 $flags = $one_table;
412             }
413 2 50       9 die "ERROR: ad_catalog requires a table name!"
414             unless $flags->{table_name};
415 2         4 $table_name = $flags->{table_name};
416 2   50     6 $flags->{format} ||= 'Base';
417 2   50     5 $flags->{file_name} ||= '';
418 2   100     10 $flags->{eol} ||= "\n";
419 2   66     9 $flags->{f_dir} ||= $dbh->{f_dir};
420 2         13 $dbh->{ad_tables}->{$table_name} = $flags;
421             }
422             }
423              
424             sub ad_dump
425             {
426 0     0   0 my $dbh = shift;
427 0         0 my $sql = shift;
428 0 0       0 if ( !$sql )
429             {
430 0         0 require Data::Dumper;
431 0         0 $Data::Dumper::Indent = 1;
432 0         0 return Data::Dumper::Dumper $dbh->func('ad_get_catalog');
433             }
434 0         0 my $txt;
435 0 0       0 my $sth = $dbh->prepare($sql) or die $dbh->errstr;
436 0 0       0 $sth->execute or die $sth->errstr;
437 0         0 my @col_names = @{ $sth->{NAME} };
  0         0  
438 0         0 $txt .= "<$_> " for @col_names;
439 0         0 $txt .= "\n";
440 0         0 while ( my @row = $sth->fetchrow_array )
441             {
442 0         0 for (@row)
443             {
444 0   0     0 $_ ||= '';
445 0         0 s/^\s*//;
446 0         0 s/\s*$//;
447 0         0 $txt .= "[$_] ";
448             }
449 0         0 $txt .= "\n";
450             }
451 0         0 return $txt;
452             }
453              
454             # END OF DRIVER PRIVATE METHODS
455              
456             sub get_avail_tables
457             {
458 0     0   0 my $dbh = $_[0];
459              
460 0         0 my @tables = $dbh->SUPER::get_avail_tables();
461              
462 0         0 my $catalog = $dbh->func( '', 'ad_get_catalog' );
463 0 0       0 if ($catalog)
464             {
465 0         0 for ( keys %{$catalog} )
  0         0  
466             {
467 0         0 push( @tables, [ undef, undef, $_, "TABLE", "AnyData" ] );
468             }
469             }
470              
471 0         0 return @tables;
472             }
473              
474             sub DESTROY
475             {
476 1     1   931 my $dbh = shift;
477 1         4 $dbh->{ad_tables} = {};
478 1         13 $dbh->STORE( 'Active', 0 );
479             }
480              
481             package DBD::AnyData::st; # ====== STATEMENT ======
482              
483 2     2   16 use strict;
  2         3  
  2         73  
484 2     2   12 use warnings;
  2         3  
  2         66  
485              
486 2     2   25 use vars qw($imp_data_size);
  2         5  
  2         153  
487              
488             $DBD::AnyData::st::imp_data_size = 0;
489             @DBD::AnyData::st::ISA = qw(DBI::DBD::SqlEngine::st);
490              
491             # sub DESTROY ($) { undef; }
492              
493             # sub finish ($) {}
494              
495             package DBD::AnyData::Statement;
496              
497 2     2   10 use strict;
  2         4  
  2         53  
498 2     2   10 use warnings;
  2         3  
  2         770  
499              
500             @DBD::AnyData::Statement::ISA = qw(DBI::DBD::SqlEngine::Statement);
501              
502             sub open_table ($$$$$)
503             {
504 7     7   37609 my ( $self, $data, $tname, $createMode, $lockMode ) = @_;
505 7         16 my $dbh = $data->{Database};
506 7         49 my $catalog = $dbh->func( $tname, 'ad_get_catalog' );
507 7 50       19 if ( !$catalog )
508             {
509 0         0 $dbh->func( [ [ $tname, 'Base', '' ] ], 'ad_catalog' );
510 0         0 $catalog = $dbh->func( $tname, 'ad_get_catalog' );
511 0         0 $createMode = 'o';
512 0         0 $lockMode = undef;
513             }
514 7         14 my $format = $catalog->{format};
515 7         20 my $file = $catalog->{file_name};
516 7   33     53 my $ad = $catalog->{ad}
517             #################################################################
518             # Patch from Wes Hardaker
519             #################################################################
520             # || AnyData::adTable( $format, $file, $createMode, $lockMode,
521             # $catalog );
522             || AnyData::adTable( $format, $file, $createMode, $lockMode, $catalog, $tname );
523             #print join("\n", $format,@$file,$createMode), "\n";
524             #use Data::Dumper; print Dumper $catalog;
525             #################################################################
526 7         24566 my $table = $ad->prep_dbd_table( $tname, $createMode );
527 7         943 my $cols = $table->{col_names};
528 7 50 66     52 if ( $cols and ref $cols ne 'ARRAY' )
529             {
530             #$dbh->DBI::set_err(99, "\n $cols\n ");
531 0         0 print "\n $cols\n ";
532 0         0 exit;
533             }
534 7 50 33     2485 if ( 'Base XML HTMLtable' =~ /$catalog->{format}/
      33        
535             or $file =~ /http:|ftp:/
536             or ref($file) eq 'ARRAY' )
537             {
538 0         0 $ad->seek_first_record();
539 0         0 $dbh->func( $tname, 'ad', $ad, 'ad_mod_catalog' );
540             }
541              
542 7         65 return DBD::AnyData::Table->new($table);
543             }
544              
545             package DBD::AnyData::Table;
546              
547 2     2   11 use strict;
  2         4  
  2         68  
548 2     2   10 use warnings;
  2         3  
  2         96  
549              
550 2     2   12 use Params::Util qw(_HASH0);
  2         3  
  2         1990  
551              
552             @DBD::AnyData::Table::ISA = qw(DBI::DBD::SqlEngine::Table);
553              
554             sub new
555             {
556 7     7   14 my ( $proto, $attr ) = @_;
557 7         25 $attr->{col_names} = $attr->{ad}->{storage}->{col_names};
558 7         20 $attr->{col_nums} = $attr->{ad}->{storage}->{col_nums};
559 7 50 33     57 delete $attr->{col_nums} unless ( defined( $attr->{col_nums} ) and defined( _HASH0( $attr->{col_nums} ) ) );
560 7         49 return $proto->SUPER::new($attr);
561             }
562              
563             sub trim
564             {
565 0     0     my $x = $_[0];
566 0           $x =~ s/^\s+//;
567 0           $x =~ s/\s+$//;
568 0           return $x;
569             }
570              
571             sub fetch_row ($$$)
572             {
573 0     0     my ( $self, $data, $row ) = @_;
574 0           my $requested_cols = $data->{sql_stmt}->{NAME};
575 0           my $dbh = $data->{Database};
576 0           my $fields = $self->{ad}->fetch_row($requested_cols);
577 0 0         if ( $dbh->{ChopBlanks} )
578             {
579 0           @$fields = map( $_ = &trim($_), @$fields );
580             }
581 0           $self->{row} = $fields;
582 0           return $self->{row};
583             }
584              
585             sub push_names ($$$)
586             {
587 0     0     my ( $self, $data, $names ) = @_;
588             #print @$names;
589 0           $self->{ad}->push_names($names);
590             }
591              
592             sub push_row ($$$)
593             {
594 0     0     my ( $self, $data, $fields ) = @_;
595 0           my $requested_cols = [];
596 0           my @rc = $data->{sql_stmt}->columns();
597 0           push @$requested_cols, $_->{column} for @rc;
598 0           unshift @$fields, $requested_cols;
599 0           $self->{ad}->push_row(@$fields);
600 0           1;
601             }
602              
603             sub seek ($$$$)
604             {
605 0     0     my ( $self, $data, $pos, $whence ) = @_;
606 0           $self->{ad}->seek( $pos, $whence );
607             }
608              
609             sub drop ($$)
610             {
611 0     0     my ( $self, $data ) = @_;
612 0           return $self->{ad}->drop();
613             }
614              
615             sub truncate ($$)
616             {
617 0     0     my ( $self, $data ) = @_;
618 0           $self->{ad}->truncate($data);
619             }
620              
621             sub DESTROY
622             {
623             # wierd: this is needed to close file handle ???
624 0     0     my $self = shift;
625             #print "CLOSING" if $self->{ad}->{storage}->{fh};
626 0 0         my $fh = $self->{ad}->{storage}->{fh} or return;
627 0           $self->{ad}->DESTROY;
628 0           undef $self->{ad}->{storage}->{fh};
629             }
630              
631             =head1 NAME
632              
633             DBD::AnyData - DBI access to XML, CSV and other formats
634              
635             =head1 SYNOPSIS
636              
637             use DBI;
638             my $dbh = DBI->connect('dbi:AnyData(RaiseError=>1):');
639             $dbh->func( 'trains', 'CSV', '/users/joe/cars.csv', 'ad_catalog');
640             $dbh->func( 'bikes', 'XML', [$xml_str], 'ad_import');
641             $dbh->func( 'cars', 'DBI', $mysql_dbh, 'ad_import');
642             #
643             # ... DBI/SQL methods to access/modify the tables 'cars','bikes','trains'
644             #
645             print $dbh->func( 'cars', 'HTMLtable', 'ad_export');
646              
647             or
648              
649             use DBI;
650             my $dbh = DBI->connect('dbi:AnyData(RaiseError=>1):');
651             $dbh->func( 'Pipe', 'data.pipe', 'XML', 'data.xml', 'ad_convert');
652              
653             or
654              
655             (many combinations of a dozen other data formats, see below)
656              
657             =head1 DESCRIPTION
658              
659             The DBD::AnyData module provides a DBI/SQL interface to data in many
660             formats and from many sources.
661              
662             Currently supported formats include general format flatfiles (CSV, Fixed
663             Length, Tab or Pipe "delimited", etc.), specific formats (passwd files,
664             web logs, etc.), a variety of other kinds of formats (XML, Mp3, HTML
665             tables), and, for some operations, any DBI accessible database. The
666             number of supported formats will continue to grow rapidly since there
667             is an open API making it easy for any author to create additional format
668             parsers which can be plugged in to AnyData.
669              
670             Data in these various formats can come from local files, from remote files,
671             or from perl data structures such as strings and arrays.
672              
673             Regardless of the format or source of the data, it may be accessed and/or
674             modified using all standard DBI methods and a subset of SQL syntax.
675              
676             In addition to standard database access to files, the module also supports
677             in-memory tables which allow you to create temporary views; to combine data
678             from a number of sources; to quickly prototype database systems; and to
679             display or save the data in any of the supported formats (e.g. to display
680             data in a CSV file as an HTML table). These in-memory tables can be
681             created from any combination of DBI databases or files of any format.
682             They may also be created from perl data structures which means it's
683             possible to quickly prototype a database system without any file access
684             or rdbms backend.
685              
686             The module also supports converting files between any of the supported
687             formats (e.g. save selected data from MySQL or Oracle to an XML file).
688              
689             Here a just a few examples of the capabilities:
690              
691             # SELECT DATA FROM A PASSWD FILE
692             #
693             $dbh->func( 'users', 'Passwd', '/etc/passwd', 'ad_catalog');
694             my $sth = $dbh->prepare("SELECT username,homedir,GID FROM users');
695              
696             # INSERT A NEW ROW INTO A CSV FILE
697             #
698             $dbh->func( 'cars', 'CSV', 'cars.csv', 'ad_catalog');
699             $dbh->do("INSERT INTO cars VALUES ('Honda','Odyssey')");
700              
701             # READ A REMOTE XML FILE AND PRINT IT AS AN HTML TABLE
702             #
703             print $dbh->func( 'XML', $url, 'HTMLtable', 'ad_convert');
704              
705             # CONVERT A MYSQL DATABASE INTO XML AND SAVE IT IN A NEW FILE
706             #
707             $dbh->func( 'DBI', $mysql_dbh, 'XML', 'data.xml', 'ad_convert');
708              
709             # CREATE AND ACCESS A VIEW CONTAINING DATA FROM AN ORACLE DATABASE
710             # AND A TAB DELIMITED FILE
711             #
712             $dbh->func( 'combo', 'DBI', $oracle_dbh, 'ad_import');
713             $dbh->func( 'combo', 'Tab', 'data.tab', 'ad_import');
714             my $sth = $dbh->prepare("SELECT * FROM combo");
715              
716              
717             =head1 INSTALLATION
718              
719             To use DBD::AnyData you will need to install these modules,
720             all available from CPAN and most available from activeState.
721              
722             * DBI
723             * DBI::DBD::SqlEngine
724             * SQL::Statement
725             * AnyData
726             * DBD::AnyData
727              
728             Note: DBI::DBD::SqlEngine is part of the DBI distribution
729              
730             Some advanced features require additional modules:
731              
732             =over 4
733              
734             =item remote file access
735              
736             requires L (the libwww bundle)
737              
738             =item XML access
739              
740             requires L and L
741              
742             =item HTML table
743              
744             access requires L and L
745              
746             =item HTML table writing
747              
748             requires L
749              
750             =back
751              
752             AnyData and DBD::AnyData themselves can either be installed via cpan,
753             cpanplus or cpanminus, using the distributed Build.PL manually with
754              
755             perl Build.PL
756             ./Build
757             ./Build test
758             ./Build install
759              
760             or by copying the AnyData.pm file manually to it's right place within
761             your perl library path.
762              
763             =head1 QUICK START
764              
765             =head2 The Basics
766              
767             =over 1
768              
769             =item There are four main steps in using DBD::AnyData in a script:
770              
771             1. Specify that you want to use the DBI module
772             2. Create a database handle
773             3. Specify the tables, files, and formats you want
774             4. Use DBI/SQL commands to access and/or modify the data
775              
776             Steps #1, #2, and #3 can be as little as a single line of code each.
777              
778             Steps #3 and #4 can be omitted in some situations, see the sections
779             below on "Working with In-Memory Data" and "Converting Data"
780              
781             =item Step #1 : Specify that you want to use the DBI module
782              
783             This step is always the same: just put this at the top of your script:
784              
785             use DBI;
786              
787             =item Step #2 Create a Database Handle
788              
789             This step can vary slightly depending on your needs but is usually this:
790              
791             my $dbh = DBI->connect('dbi:AnyData(RaiseError=>1):');
792              
793             See the section below on "Connection Options" for other forms of
794             connecting. See the section below on "Using Multiple Databases" for
795             cases in which you may be creating more than one database handle.
796              
797             =item Step #3 : Specify the tables, files, and formats
798              
799             This step makes use of one of several methods unique to DBD::AnyData.
800             These methods use the database handle created in step #2 to make a
801             func() call and specify the name of the method as the last parameter.
802             For example the 'ad_catalog' method would be called like this:
803              
804             $dbh->func( ..., 'ad_catalog')
805              
806             The ad_catalog() method takes three required parameters and one
807             optional parameter:
808              
809             # $table = the name you will use to refer to the table in SQL commands
810             # $format = the format of the data ('XML', 'CSV', 'Fixed', etc.)
811             # $file = the name of a local or remote file holding the data
812             # $flags = an optional hash of flags required by some data formats
813             $dbh->func( $table, $format, $file, $flags, 'ad_catalog')
814              
815             # For example:
816             $dbh->func( 'cars', 'XML', 'cars.xml', 'ad_catalog' )
817              
818             This specifies that the table name 'cars' will be used to
819             access XML data stored in the file 'cars.xml'.
820              
821             Once you have issued a catalog command, you can use the name $table
822             in SQL commands to access or modify the data in $file. The catalog
823             only needs to be specified once for a table/file/format combination
824             and can then be used for an unlimited number of processing commands.
825              
826             =item Step #4 : Use DBI/SQL commands to access and/or modify data
827              
828             DBD::AnyData supports all standard DBI methods and a subset of SQL
829             syntax. See the section below "SQL Syntax" for a description of the
830             supported SQL commands. See the DBI documentation for detailed
831             description of DBI commands.
832              
833             The do() method can be used to create or drop a table and insert, delete,
834             or update rows:
835              
836             $dbh->do("CREATE TABLE ... )
837             $dbh->do("DROP TABLE ... )
838             $dbh->do("INSERT INTO ... )
839             $dbh->do("UPDATE ... )
840             $dbh->do("DELETE ... )
841              
842             A combination of the prepare(), execute(), and fetch() methods can be
843             used to access data:
844              
845             my $sth = $dbh->prepare("SELECT * FROM cars WHERE make = 'Honda'");
846             $sth->execute();
847             while (my $row = $sth->fetchrow_hashref){
848             print $row->{model};
849             }
850              
851             =item Putting it all together
852              
853             This is the complete script needed to access data stored in
854             CSV format in a file called "cars.csv". It prints all data
855             from the "make" and "model" columns of the database.
856              
857             # specifies that you will use the DBI module.
858             use DBI;
859             # creates a database handle
860             my $dbh = DBI->connect('dbi:AnyData(RaiseError=>1):');
861             # specifies the table, format, and file holding the data
862             $dbh->func( 'cars', 'CSV', 'cars.csv' 'ad_catalog');
863             # through 8 use DBI and SQL to access data in the file
864             my $sth = $dbh->prepare("SELECT make, model FROM cars");
865             $sth->execute();
866             while (my $row = $sth->fetch) {
867             print "@$row\n";
868             }
869              
870             =back
871              
872             =head2 Customizing table structure
873              
874             DBD::AnyData uses a number of defaults when it decides how to read data
875             from a database and in many cases these defaults are all you will need.
876             However, depending on the format and database you are using, you may need
877             to specify other features such as column names, record separators, etc.
878              
879             You can specify this additional information in the $flags parameter of the
880             ad_catalog and other DBD::AnyData methods. $flags is always a reference
881             to a hash, i.e. one or more key value pairs joined with a =>, separated by
882             commas, and delimited by curly braces:
883              
884             $flags = { key1 => value1, key2 => value2 ... }
885              
886             # or in the method call:
887             $dbh->func( $table, $format, $file, { key1=>,val1 ... }, 'ad_catalog');
888              
889             =over 2
890              
891             =item Column Names
892              
893             Some formats have pre-defined column names:
894              
895             Passwd username
896             passwd
897             UID
898             GID
899             fullname
900             homedir
901             shell
902              
903             Weblog remotehost
904             usernname
905             authuser
906             date
907             request
908             status
909             bytes
910             referer
911             client
912              
913             Mp3 song
914             artist
915             album
916             year
917             genre
918             filename
919             filesize
920              
921             Column names for the other formats can either be specified in the database
922             itself or supplied by you in the $flags parameter.
923              
924             If the column names are specified in the database, they are taken from
925             the first record in the database. For example in a CSV (Comma
926             Separated Values) file or a Fixed Length file, the default is to treat
927             the first line of the table as the list of column names. In an
928             HTMLtable file, the default is to look for the first
929             table. In an XML file, the default is to use the names of all
930             attributes and all CDATA and PCDATA elements contained within the first
931             non-initial tag.
932              
933             In most cases, this first record that defines the column names is in
934             the same format as the rest of the table e.g. a CSV string in a CSV
935             file, a tab delimited string in a Tab delimited file, etc. The one
936             exception to this is that in a Fixed Length file the first row of the
937             file can contain a *comma-separated* list of column names, not a fixed
938             length list. HTMLtable and XML also use other flags to select the
939             column names (e.g. the number of the table or the depth in the tree to
940             examine). Please see the documentation for these formats for further
941             details of how defaults are selected.
942              
943             For most formats, if the column names are not contained in the first
944             record in the file, then you can specify them as a comma separated
945             list in the $flags parameter, for example:
946              
947             $dbh->func(
948             'cars',
949             'Tab',
950             'data.tab',
951             { col_names => 'make,model,year' },
952             'ad_catalog')
953              
954             =back
955              
956             =head1 SUPPORTED FORMATS
957              
958             =head2 CSV, Tab, Pipe, Ini, Paragraph
959              
960             =head2 Fixed
961              
962             Fixed Length format files (where each column is a specified length)
963             are unique in several respects. First, as mentioned above, if you
964             wish to include the column names in the file itself, they should be on
965             the first line of the file as a *comma separated* string.
966              
967             Secondly, there is a mandatory flag called 'pattern' that you must use
968             whenever you use the Fixed length format. This flag specifies the
969             widths of the columns. It uses the standard Perl pack/unpack syntax
970             to specify the pattern. See the Perl documentation for those commands
971             for further details. In most cases simply using a capital 'A'
972             followed by the length of the field suffices:
973              
974             { pattern => 'A10 A12 A4' }
975              
976             This specifies that the table contains three fields with widths of 10,
977             12, and 14 characters.
978              
979             =head2 XML
980              
981             =head2 HTMLtable
982              
983             =head2 DBI
984              
985             DBD::AnyData supports importing any DBI database into memory and can
986             also convert any DBI database into any of the other AnyData formats.
987              
988             Use the format name 'DBI', and instead of a filename, pass the
989             ad_import call a connection in whatever database you are using, and
990             specify a SQL SELECT statement:
991              
992             my $dbh = DBI->connect('dbi:AnyData:(RaiseError=>1)');
993             $dbh->func(
994             'table1',
995             'DBI',
996             DBI->connect('dbi:mysql:database=test:(RaiseError=>1)'),
997             {sql=>"SELECT make, model FROM cars WHERE make = 'honda'"},
998             'ad_import');
999              
1000             That snippet imports a view from a MySQL database (selecting only the
1001             named columns and the selected rows) into an AnyData in-memory table.
1002             It can then be queried and/or modified in memory and then either
1003             displayed or stored to a file in some other format such as XML.
1004              
1005             You may also use a bind_parameters form for the SQL call by passing an
1006             additional flag with an arrayref of the parameters:
1007              
1008             {
1009             sql => "SELECT make,model FROM CARS WHERE make = ?"
1010             params => ['honda']
1011             }
1012              
1013             To convert from a DBI accessible database such as ORACLE or MySQL to
1014             one of the AnyData formats such as XML you must also include a flag
1015             with the table_name within the database:
1016              
1017             my $dbh = DBI->connect('dbi:AnyData:(RaiseError=>1)');
1018             $dbh->func(
1019             'DBI',
1020             DBI->connect('dbi:mysql:database=test:(RaiseError=>1)'),
1021             'XML',
1022             'cars.xml',
1023             {table_name=>'cars'},
1024             'ad_convert');
1025              
1026             Or to print out the same data as an HTML table without storing it:
1027              
1028             my $dbh = DBI->connect('dbi:AnyData:(RaiseError=>1)');
1029             print $dbh->func(
1030             'DBI',
1031             DBI->connect('dbi:mysql:database=test:(RaiseError=>1)'),
1032             'HTMLtable',
1033             undef,
1034             {table_name=>'cars'},
1035             'ad_convert');
1036              
1037             The ad_convert() method works on the entire database. If you need to
1038             convert only a selected portion of the databse, use ad_import() with
1039             a SELECT clause and then ad_export() it to the new format.
1040              
1041             The ad_import method by default closes the connection for the imported
1042             database. If you need to continue using the handle for the other datbase,
1043             pass the flag {keep_connection=>1}:
1044              
1045             my $dbh = DBI->connect('dbi:AnyData:(RaiseError=>1)');
1046             my $mysql_dbh = DBI->connect('dbi:mysql:database=test:(RaiseError=>1)'),
1047             $dbh->func(
1048             'cars',
1049             'DBI',
1050             $mysql_dbh,
1051             { keep_connection=>1 },
1052             'ad_import');
1053             #...
1054             $mysql_dbh->disconnect;
1055              
1056             =head2 Passwd, Weblog, Mp3
1057              
1058             =head2 Other Formats
1059              
1060             DBD::AnyData supports an open API that allows other authors to build support
1061             for other formats. This means that the list of supported formats will
1062             continually grow. At the moment Wes Hardaker is working on
1063             AnyData::Format::SNMP and Earl Cahill is working on
1064             AnyData::Format::Storable. Anyone who is interested in working on a new
1065             format module, please open a ticket with an appropriate patch or
1066             write to dbi-dev@perl.org.
1067              
1068             =head1 FURTHER DETAILS
1069              
1070             =head2 Converting between formats
1071              
1072             The $dbh->func(...,'ad_convert') method provides a one-step way to
1073             convert between any of the data formats supported by DBD::AnyData.
1074             For example: read a CSV file and save it as an XML file or vice versa.
1075             See the section below on "convert" for details. See the section on
1076             "Working with other DBI databases" for information on converting data
1077             from ORACLE, or MySQL or almost any other database into XML, CSV, or
1078             any of the DBD::AnyData formats.
1079              
1080             =head2 Using remote files
1081              
1082             You can import remote files accessible by FTP or HTTP directly into a
1083             DBD::AnyData in memory database using 'ad_import' or you can use ad_convert
1084             to print the remote files as strings or save them to a local file.
1085             If the $file parameter of ad_import or ad_convert starts with "ftp" or
1086             "http", DBD::AnyData will call LWP behind the scenes and fetch the file.
1087              
1088             This will fetch the remote file, parse its XML, and provide you with
1089             an in-memory table which you can query with DBI/SQL or save to a local
1090             file:
1091              
1092             $dbh->func(
1093             'news',
1094             'XML',
1095             'http://www.somewhere.org/files/news.xml',
1096             'ad_import');
1097              
1098             This will fetch the remote file, parse its XML, and print it out
1099             as an HTML table:
1100              
1101             print $dbh->func(
1102             'XML',
1103             'http://www.somewhere.org/files/news.xml',
1104             'HTMLtable',
1105             'ad_convert');
1106              
1107             If the remote file requires authorization, you can include values for
1108             "user" and "pass" in the $flags parameter:
1109              
1110             $dbh->func(
1111             'news',
1112             'XML',
1113             'http://www.somewhere.org/news.xml',
1114             { user => 'fred', passwd => 'x9y77d' },
1115             'ad_import');
1116              
1117             =head2 Working with in-memory tables
1118              
1119             In addition to normal file storage databases, DBD::AnyData supports
1120             databases that are stored and modified in-memory. You may either simply
1121             query the databases and then close them, or you can use the ad_export
1122             method to display data to the screen or save it to a file. There are a
1123             variety of reasons you might want to work with in-memory databases,
1124             including:
1125              
1126             =over 4
1127              
1128             =item Prototyping
1129              
1130             quickly create a database from a string, an array, or the DATA section of
1131             a script without needing any file access or rdbms.
1132              
1133             =item Creating Views
1134              
1135             pull selected columns and selected rows from an ORACLE or MySQL database
1136             en masse and work with them in memory rather than having to use the full
1137             database.
1138              
1139             =item Combining Data from multiple formats
1140              
1141             create a single in-memory table by importing selected columns and rows
1142             from e.g. an XML file, an Oracle database, and a CSV file.
1143              
1144             =item Rollback/Commit
1145              
1146             You can make multiple changes to the in-memory database and then,
1147             depending on the sucess or failure of those changes either commit by using
1148             export to save the changes to disk or skip export which effectively rolls
1149             back the database to its state before the import.
1150              
1151             =back
1152              
1153             In-memory tables may be modified with DBI/SQL commands and can then be
1154             either printed to the screen or saved as a file in any of the AnyData
1155             formats. (see the ad_export method below)
1156              
1157             In-memory tables may be created in several ways:
1158              
1159             1. Create and populate the table from one or more local or remote files
1160             2. Create and populate the table from a string
1161             3. Create and populate the table from an array
1162             4. Use DBI/SQL commands to create & populate the table
1163              
1164             =over 4
1165              
1166             =item Creating in-memory tables from local or remote files
1167              
1168             You can create an in-memory table from a string in a specified format,
1169             Note: the string should be enclosed in square brackets.
1170              
1171             This reads a CSV file into an in-memory table. Further access and
1172             modification takes place in-memory without further file access unless
1173             you specifically use ad_export to save the table to a file.
1174              
1175             # CREATE A TABLE FROM A LOCAL FILE
1176             $dbh->func( 'test2', 'CSV', $filename, 'ad_import');
1177              
1178             # CREATE A TABLE FROM A REMOTE FILE
1179             $dbh->func( 'test2', 'CSV', $url, 'ad_import');
1180              
1181             See the section on "Remote File Access" for further details of using
1182             remote Files.
1183              
1184             =item Creating an in-memory table from Strings
1185              
1186             You can create an in-memory table from a string in a specified format,
1187             Note: the string should be enclosed in square brackets.
1188              
1189             This example creates an in-memory table from a CSV string:
1190              
1191             # CREATE A TABLE FROM A CSV STRING
1192             $dbh->func( 'test2', 'CSV',
1193             ["id,phrase\n1,foo\n2,bar"],
1194             'ad_import');
1195              
1196             =item Creating an in-memory table from the DATA section of a script
1197              
1198             Perl has the really cool feature that if you put text after the
1199             marker __END__, you can access that text as if it were from a
1200             file using the DATA array. This can be great for quick prototyping.
1201              
1202             For example this is a complete script to build and access a small
1203             table and print out "Just Another Perl Hacker":
1204              
1205             use DBI;
1206             my $dbh=DBI->connect('dbi:AnyData(RaiseError=>1):');
1207             $dbh->func( 'test', 'XML', [], 'ad_import');
1208             print $dbh->selectcol_arrayref(qq{
1209             SELECT phrase FROM test WHERE id = 2
1210             })->[0];
1211             __END__
1212            
1213             Hello World!
1214             Just Another Perl Hacker!
1215            
1216              
1217             The same idea can be used with DATA sections of any size in any of
1218             the supported formats.
1219              
1220             =item Creating an in-memory table from Arrays
1221              
1222             In-memory tables may also be created from arrays. Or, more technically,
1223             from references to arrays. The array should consist of rows which are
1224             themselves references to arrays of the row values. The first row should
1225             be column names.
1226              
1227             For example:
1228              
1229             # CREATE A TABLE FROM AN ARRAY
1230             $dbh->func( 'test3', 'ARRAY',
1231             [
1232             ['id','phrase'],
1233             [1,'foo'],
1234             [2,'bar']
1235             ],
1236             'ad_import');
1237              
1238             =item Creating an in-memory table from DBI/SQL commands
1239              
1240             If you do not use ad_catalog or ad_import to associate a table
1241             name with a file, then the table will be an in-memory table, so
1242             you can just start right out by using it in DBI/SQL commands:
1243              
1244             # CREATE & POPULATE A TABLE FROM DBI/SQL COMMANDS
1245             use DBI;
1246             my $dbh = DBI->connect('dbi:AnyData(RaiseError=>1):');
1247             $dbh->do("CREATE TABLE test (id TEXT,phrase TEXT)");
1248             $dbh->do("INSERT INTO test VALUES (1,'foo')");
1249             $dbh->do("INSERT INTO test VALUES (2,'bar')");
1250             $dbh->do("UPDATE test SET phrase='baz' WHERE id = '2'");
1251             $dbh->do("DELETE FROM test WHERE id = '1'");
1252              
1253             =back
1254              
1255             =head2 Using Multiple Databases, Simulating Joins
1256              
1257             You may access any number of databases within a single script and can mix
1258             and match from the various data formats.
1259              
1260             For example, this creates two in-memory tables from two different data
1261             formats
1262              
1263             $dbh->func( 'classes', 'CSV', 'classes.csv' 'ad_import');
1264             $dbh->func( 'profs', 'XML', 'profs.xml', 'ad_import');
1265              
1266             You can also import columns from several different formats into a single
1267             table. For example this imports data from an XML file, a CSV file and a
1268             Pipe delimited file into a single in-memory database. Note that the
1269             $table parameter is the same in each call so the data from each import
1270             will be appended into that one table.
1271              
1272             $dbh->func( 'test', 'XML', [$xmlStr], 'ad_import');
1273             $dbh->func( 'test', 'CSV', [$csvStr], 'ad_import');
1274             $dbh->func( 'test', 'Pipe', [$pipeStr], 'ad_import');
1275              
1276             When you import more than one table into a single table like this, the
1277             resulting table will be a cross join unless you supply a lookup_key flag.
1278             If a lookup_key is supplied, then a the resulting table will be a full
1279             outer join on that key column. This feature is experimental for the time
1280             being but should work as expected unless there are columns other than the
1281             key column with the same names in the various tables. You can specify
1282             that the joined table will only contain certain columns by creating a
1283             blank empty table before doing the imports. You can specify only certain
1284             rows with the sql flag. For example:
1285              
1286             $dbh->func('test','ARRAY',[],{col_names=>'foo,bar'baz'}, 'ad_import');
1287             $dbh->func('test','XML',$file1,{lookup_key=>'baz'},'ad_import');
1288             $dbh->func('test','CSV',$file1,{lookup_key=>'baz'},'ad_import');
1289              
1290             DBD::AnyData does not currently support using multiple tables in a
1291             single SQL statement. However it does support using multiple tables
1292             and querying them separately with different SQL statements. This
1293             means you can simulate joins by creating two statement handles and
1294             using the values from the first handle as a lookup key for the second
1295             handle. Like this:
1296              
1297             $dbh->func( 'classes', 'CSV', 'classes.csv' 'ad_import');
1298             $dbh->func( 'profs', 'XML', 'profs.xml', 'ad_import');
1299             my $classes_sth = $dbh->prepare( "SELECT pid,title FROM classes" );
1300             my $profs_sth = $dbh->prepare( "SELECT name FROM profs WHERE pid = ?" );
1301             $classes_sth->execute;
1302             while (my($pid,$class_title) = $classes_sth->fetchrow_array) {
1303             $profs_sth->execute($pid);
1304             my $row = $profs_sth->fetchrow_arrayref;
1305             my $prof_name = $row ? $row->[0] : '';
1306             print "$class_title : $prof_name\n";
1307             }
1308              
1309             # That will produce the same results as:
1310             SELECT classes.title,profs.name FROM classes,profs WHERE pid = pid
1311              
1312             =head1 REFERENCE
1313              
1314             =head2 Overview of DBD::AnyData Methods
1315              
1316             DBD::AnyData makes use of five methods not found in other drivers:
1317              
1318              
1319             =over 12
1320              
1321             =item ad_catalog
1322              
1323             specifies a file to be used for DBI/SQL continuous file access
1324              
1325             =item ad_import
1326              
1327             imports data into an in-memory table
1328              
1329             =item ad_export
1330              
1331             exports data from an in-memory table to a file
1332              
1333             =item ad_clear
1334              
1335             clears an in-memory table (deletes it from memory)
1336              
1337             =item ad_convert
1338              
1339             converts data from one format to another and either saves it in a new file
1340             or returns it as a string
1341              
1342             =back
1343              
1344             These methods are called using DBI func(), for example:
1345              
1346             $dbh->func( $table, $format, 'ad_export');
1347              
1348             # Here are the parameters for the various methods:
1349             $dbh->func( $table, $format, $file, $flags, 'ad_catalog');
1350             $dbh->func( $table, $format, $data, $flags, 'ad_import');
1351              
1352             $dbh->func( $source_format, $source_data,
1353             $target_format, $target_file,
1354             $source_flags, $target_flags,
1355             'ad_convert');
1356              
1357             $dbh->func( $table, $format, $file, $flags, 'ad_export');
1358             $dbh->func( $table, 'ad_clear' );
1359            
1360             # $table is a valid SQL table name
1361             # $format is one of the AnyData formats ('XML','CSV',etc.)
1362             # $file is a valid file name (relative or absolute) on the local computer
1363             # $flags is a hashref containing key/value pairs, e.g.
1364             { col_names => 'make,model,year', pattern => 'A10 A12 A4' }
1365              
1366             # $data is one of:
1367             # * a valid file name (relative or absolute) on the local computer
1368             # * a valid absolute FTP or HTTP URL
1369             # * an arrayref containing arrayrefs of rows with column names first
1370             # [
1371             # ['make','model'],
1372             # ['Honda','Odyssy'],
1373             # ['Ford','Suburban'],
1374             # ]
1375              
1376             # * an arrayref containing a string in a specified format
1377             # CSV : ["id,phrase\n1,foo\n2,bar"]
1378             # Pipe : ["id|phrase\n1|foo\n2|bar"]
1379              
1380             # * a reference to the DATA section of a file
1381             # []
1382              
1383             # * a DBI Database handle
1384             # DBI->connect('dbi:mysql:database=...)
1385              
1386             The ad_catalog method is the standard way to treat files as databases.
1387             Each time you access data, it is read from the file and each time you
1388             modify data, it is written to the file. The entire file is never read
1389             en masse into memory unless you explicitly request it.
1390              
1391             The ad_import method can import data from local or remote files,
1392             from any other DBI accessible database, from perl data structures such
1393             as arrays and strings. You may import an entire table or only the columns
1394             and rows you specify. If the data is imported from a file, all of the
1395             data you select is read into memory when you call ad_import so this should
1396             not be done with selections larger than will fit in your memory. :-).
1397             All accessing and modification is done in memory. If you want to save the
1398             results of any changes, you will need to call ad_export explicitly.
1399              
1400             Not all formats and data sources will work with all methods. Here is a
1401             summary of what will work. "all sources" includes local files, remote
1402             files, any DBI accessible database, perl arrayrefs, perl strings.
1403              
1404             Import From all formats, all sources
1405             Convert From all formats, all sources
1406             Convert To all formats except DBI, local files, arrays or strings only
1407             Export To all formats except DBI, local files, arrays or strings only
1408             Catalog all formats except DBI, XML, HTMLtable, Mp3, ARRAY,
1409             local files only
1410              
1411             =head2 connect
1412              
1413             The DBI->connect call
1414              
1415             =head2 ad_catalog
1416              
1417             PURPOSE:
1418              
1419             Creates an association betweeen a table name, a data format, and a file.
1420              
1421             SYNTAX:
1422              
1423             $dbh->func( $table, $format, $file, $flags, 'ad_catalog' )
1424              
1425             PARAMETERS:
1426              
1427             $table = the name of the table to be used in SQL commands
1428              
1429             $format = an AnyData format ('XML','CSV', etc.)
1430              
1431             $file = the name of a local file (either full path or relative)
1432              
1433             $flags = a optional hashref of column names or other values
1434              
1435             EXAMPLE:
1436              
1437             This specifies that any DBI/SQL statements to the table
1438             'cars' will access and/or modify XML data in the file
1439             '/users/me/data.xml'
1440              
1441             $dbh->func( 'cars', 'XML', '/usrs/me/data.xml', 'ad_catalog' )
1442              
1443             REMARKS:
1444              
1445             The format may be any AnyData format *except* DBI, XML, HTMLtable,
1446             and MP3.
1447              
1448             =head2 ad_import
1449              
1450             PURPOSE:
1451              
1452             Imports data from any source and any format into an in-memory table.
1453              
1454             SYNTAX:
1455              
1456             $dbh->func( $table, $format, $data_source, $flags, 'ad_import' )
1457              
1458             PARAMETERS:
1459              
1460             $table = the name of the table to be used in SQL commands
1461              
1462             $format = an AnyData format ('XML','CSV', etc.)
1463              
1464             $data_source = $file_name
1465             or $url
1466             or [$string]
1467             or []
1468             or $reference_to_an array of arrays
1469             or $DBI_database_handle
1470              
1471             (See section "Data Sources" for more specifics of $data_source)
1472              
1473             EXAMPLES:
1474              
1475             $dbh->func( 'cars', 'XML', '/usrs/me/data.xml', 'ad_import' )
1476              
1477             For further examples, see sections on "In-Memory Tables",
1478             "Remote Files", "DBI databases".
1479              
1480              
1481             =head2 ad_export
1482              
1483             PURPOSE:
1484              
1485             Converts an in-memory table into a specified format and either saves
1486             it to a file or returns it as a string.
1487              
1488             SYNTAX:
1489              
1490             $dbh->func( $table, $format, $file, $flags, 'ad_export' )
1491              
1492             OR
1493              
1494             my $string = $dbh->func( $table, $format, $flags, 'ad_export' )
1495              
1496             PARAMETERS:
1497              
1498             $table = the name of the in-memory table to export
1499              
1500             $format = an AnyData format ('XML','CSV', etc.)
1501              
1502             $file = the name of a local file (either full path or relative)
1503              
1504             EXAMPLES:
1505              
1506             Save a table as an XML file:
1507              
1508             $dbh->func( 'cars', 'XML', '/usrs/me/data.xml', 'ad_export' )
1509              
1510             Print a table as an HTML table
1511              
1512             print $dbh->func( 'cars', 'HTMLtable', 'ad_export' )
1513              
1514             =head2 ad_convert
1515              
1516             PURPOSE:
1517              
1518             Converts data from one format into another and either returns it
1519             as a string in the new format or saves it to a file in the new
1520             format.
1521              
1522             SYNTAX:
1523              
1524             my $str = $dbh->func(
1525             $source_format,
1526             $data_source
1527             $target_format,
1528             $source_flags,
1529             $target_flags,
1530             'ad_convert' );
1531              
1532             OR
1533              
1534             $dbh->func(
1535             $source_format,
1536             $data_source
1537             $target_format,
1538             $target_file,
1539             $source_flags,
1540             $target_flags,
1541             'ad_convert' );
1542              
1543             PARAMETERS:
1544              
1545             $source_format = AnyData format ('XML','CSV', etc.) of the source db
1546              
1547             $target_format = AnyData format ('XML','CSV', etc.) of the target db
1548              
1549             $target_file = name of file to store converted data in
1550              
1551             $data_source = $file_name
1552             or $url
1553             or [$string]
1554             or []
1555             or $reference_to_an array of arrays
1556             or $DBI_database_handle
1557              
1558             (See section "Data Sources" for more specifics of $data_source)
1559              
1560             EXAMPLES:
1561              
1562             # CONVERT A CSV FILE TO AN XML FILE
1563             #
1564             $dbh->func( 'CSV', 'data.csv', 'XML', 'data.xml', 'ad_convert');
1565              
1566             # CONVERT AN ARRAYREF TO AN HTML TABLE AND PRINT IT
1567             #
1568             print $dbh->func( 'ARRAY', $aryref, 'HTMLtable', 'ad_convert');
1569              
1570             # CONVERT AN ARRAYREF TO XML AND SAVE IT IN A FILE
1571             #
1572             $dbh->func( 'ARRAY', $aryref, 'XML', 'data.xml', 'ad_convert');
1573              
1574             # CONVERT A SELECTION FROM A MySQL DATABASE TO XML
1575             # AND SAVE IT IN A FILE
1576             #
1577             $dbh->func(
1578             'DBI',
1579             $mysql_dbh,
1580             'XML',
1581             'data.xml',
1582             {sql=>"SELECT make,model FROM CARS where year > 1996"}
1583             'ad_convert');
1584              
1585             REMARKS
1586              
1587             The format 'DBI' (any DBI accessible database) may be used as the
1588             source of a conversion, but not as the target of a conversion.
1589              
1590             The format 'ARRAY' may be used to indicate that the source of the
1591             conversion is a reference to an array. Or that the result of the
1592             conversion should be returned as an array reference. (See above,
1593             working with in-memory database for information on the structure of
1594             the array reference).
1595              
1596              
1597             =head2 Data Sources
1598              
1599             The ad_import and ad_convert methods can take data from many
1600             sources, including local files, remote files, strings, arrays,
1601             any DBI accessible database, the DATA section of a script.
1602              
1603             The $data_source parameter to ad_import and ad_convert will
1604             vary depending on the specific data source, see below.
1605              
1606             Local Files
1607              
1608             A string containing the name of a local file. It may either
1609             be a full path, or a path or file relative to the currently
1610             defined f_dir (see ?);
1611              
1612             e.g. '/users/me/data.xml'
1613              
1614             Remote Files
1615              
1616             A string containing the url of the data. Must start with
1617             'ftp://' or 'http://'
1618              
1619             e.g. 'http://www.somewhere.org/misc/news.xml'
1620              
1621             Arrays of Arrays
1622              
1623             A reference to an array of data. Each row of the data is
1624             a reference to an array of values. The first row is the
1625             column names. E.G.:
1626              
1627             [
1628             ['make','model'],
1629             ['Honda','Odyssy'],
1630             ['Ford','Suburban'],
1631             ]
1632              
1633             Strings
1634              
1635             A string in the specified format including all field and record
1636             separators. The string should be the only row in an array reference
1637             (i.e. it should be enclosed in square brackets)
1638              
1639             e.g. a CSV string
1640              
1641             ["id,phrase\n1,foo\n2,bar"]
1642              
1643             or in Pipe Delimited string
1644              
1645             ["id|phrase\n1|foo\n2|bar"]
1646              
1647             The DATA section of a file
1648              
1649             A reference to the array obtained from the lines after
1650             __END__ in a script.
1651              
1652             []
1653              
1654             DBI Databases
1655              
1656             A database handle for a specified rdbms.
1657              
1658             DBI->connect('dbi:mysql:database=...)
1659              
1660              
1661             =head2 ad_clear
1662              
1663             PURPOSE:
1664              
1665             Clears an in-memory table (deletes it from memory)
1666              
1667             SYNTAX:
1668              
1669             $dbh->func( $table, 'ad_clear' )
1670              
1671             PARAMETERS:
1672              
1673             $table = the name of the in-memory table to clear
1674              
1675             REMARKS:
1676              
1677             In-memory tables will be deleted from memory automatically when the
1678             database handle used to create them goes out of scope. They will also
1679             be deleted if you call $dbh->disconnect() on the database handle
1680             used to create them. The ad_clear method is a way to free up memory
1681             if you intend to keep using the database handle but no longer need a
1682             given table. As with other (all?) Perl memory operations, this frees
1683             memory for the remainder of your perl script to use but does not decrease
1684             the total amount of system memory used by the script.
1685              
1686             =head2 SQL Syntax
1687              
1688             Currently only a limited subset of SQL commands are supported.
1689             Only a single table may be used in each command. This means
1690             That there are *no joins*, but see the section above on simulating
1691             joins. In coming months additional SQL capabilities will be added,
1692             so keep your eyes out for ANNOUNCE message on usenet or the dbi-users
1693             mailing list (see below "Getting More Help").
1694              
1695             Here is a brief synopsis, please see the documentation for
1696             SQL::Statement for a more complete description of these commands.
1697              
1698             CREATE TABLE $table
1699             ( $col1 $type1, ..., $colN $typeN,
1700             [ PRIMARY KEY ($col1, ... $colM) ] )
1701              
1702             DROP TABLE $table
1703              
1704             INSERT INTO $table
1705             [ ( $col1, ..., $colN ) ]
1706             VALUES ( $val1, ... $valN )
1707              
1708             DELETE FROM $table
1709             [ WHERE $wclause ]
1710              
1711             UPDATE $table
1712             SET $col1 = $val1, ... $colN = $valN
1713             [ WHERE $wclause ]
1714              
1715             SELECT [DISTINCT] $col1, ... $colN
1716             FROM $table
1717             [ WHERE $wclause ]
1718             [ ORDER BY $ocol1 [ASC|DESC], ... $ocolM [ASC|DESC] ]
1719              
1720             $wclause [NOT] $col $op $val|$col
1721             [ AND|OR $wclause2 ... AND|OR $wclauseN ]
1722              
1723             $op = | <> | < | > | <= | >=
1724             | IS NULL | IS NOT NULL | LIKE | CLIKE
1725              
1726             The "CLIKE" operator works exactly like "LIKE" but is case insensitive.
1727              
1728             =head1 BUGS
1729              
1730             Please report any bugs or feature requests to
1731             C, or through the web interface at
1732             L.
1733             I will be notified, and then you'll automatically be notified of
1734             progress on your bug as I make changes.
1735              
1736             =head1 SUPPORT
1737              
1738             You can find documentation for this module with the perldoc command.
1739              
1740             perldoc DBD::AnyData
1741              
1742             You can also look for information at:
1743              
1744             =over 4
1745              
1746             =item * RT: CPAN's request tracker
1747              
1748             L
1749              
1750             =item * AnnoCPAN: Annotated CPAN documentation
1751              
1752             L
1753              
1754             =item * CPAN Ratings
1755              
1756             L
1757              
1758             =item * Search CPAN
1759              
1760             L
1761              
1762             =back
1763              
1764             =head1 ACKNOWLEDGEMENTS
1765              
1766             Many people have contributed ideas and code, found bugs, and generally
1767             been supportive including Tom Lowery, Andy Duncan, Randal Schwartz, Michel
1768             Rodriguez, Wes Hardraker, Bob Starr, Earl Cahill, Bryan Fife, Matt Sisk,
1769             Matthew Wickline, Wolfgang Weisseberg. Thanks to Jochen Weidmann for
1770             DBD::File and SQL::Statement and of course Tim Bunce and Alligator
1771             Descartes for DBI and its documentation.
1772              
1773             =head1 AUTHOR & COPYRIGHT
1774              
1775             Copyright 2000, Jeff Zucker
1776              
1777             Copyright 2010, Jens Rehsack
1778              
1779             This program is free software; you can redistribute it and/or modify it
1780             under the terms of either: the GNU General Public License as published
1781             by the Free Software Foundation; or the Artistic License.
1782              
1783             See http://dev.perl.org/licenses/ for more information.
1784              
1785             All rights reserved
1786              
1787             =cut
1788              
1789             1; # End of DBD::AnyData