home *** CD-ROM | disk | FTP | other *** search
/ PC Professionell 2004 December / PCpro_2004_12.ISO / files / webserver / xampp / xampp-perl-addon-1.4.9-installer.exe / AnyData.pm < prev    next >
Encoding:
Perl POD Document  |  2002-06-14  |  53.7 KB  |  1,591 lines

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