File Coverage

blib/lib/DBD/CSV.pm
Criterion Covered Total %
statement 201 212 94.8
branch 78 110 70.9
condition 25 41 60.9
subroutine 29 30 96.6
pod n/a
total 333 393 84.7


line stmt bran cond sub pod time code
1             #!/usr/bin/perl
2             #
3             # DBD::CSV - A DBI driver for CSV and similar structured files
4             #
5             # This module is currently maintained by
6             #
7             # H.Merijn Brand <h.m.brand@xs4all.nl>
8             #
9             # See for full acknowledgements the last two pod sections in this file
10              
11 24     24   12537990 use strict;
  24         51  
  24         947  
12 24     24   113 use warnings;
  24         42  
  24         4796  
13              
14             require DynaLoader;
15             require DBD::File;
16             require IO::File;
17              
18             our @f_SHORT = qw( class file dir dir_search ext lock lockfile schema encoding );
19             our @c_SHORT = qw( eof
20             eol sep_char quote_char escape_char binary decode_utf8 auto_diag
21             diag_verbose blank_is_undef empty_is_undef allow_whitespace
22             allow_loose_quotes allow_loose_escapes allow_unquoted_escape
23             always_quote quote_empty quote_space escape_null quote_binary
24             keep_meta_info callbacks );
25              
26             package DBD::CSV;
27              
28 24     24   220 use strict;
  24         56  
  24         3663  
29              
30             our @ISA = qw( DBD::File );
31              
32             our $VERSION = "0.62";
33             our $ATTRIBUTION = "DBD::CSV $DBD::CSV::VERSION by H.Merijn Brand";
34              
35             our $err = 0; # holds error code for DBI::err
36             our $errstr = ""; # holds error string for DBI::errstr
37             our $sqlstate = ""; # holds error state for DBI::state
38             our $drh = undef; # holds driver handle once initialized
39              
40       0     sub CLONE { # empty method: prevent warnings when threads are cloned
41             } # CLONE
42              
43             # --- DRIVER -------------------------------------------------------------------
44              
45             package DBD::CSV::dr;
46              
47 24     24   156 use strict;
  24         142  
  24         638  
48              
49 24     24   1264 use Text::CSV_XS ();
  24         29430  
  24         10789  
50              
51             our @CSV_TYPES = (
52             Text::CSV_XS::IV (), # SQL_TINYINT
53             Text::CSV_XS::IV (), # SQL_BIGINT
54             Text::CSV_XS::PV (), # SQL_LONGVARBINARY
55             Text::CSV_XS::PV (), # SQL_VARBINARY
56             Text::CSV_XS::PV (), # SQL_BINARY
57             Text::CSV_XS::PV (), # SQL_LONGVARCHAR
58             Text::CSV_XS::PV (), # SQL_ALL_TYPES
59             Text::CSV_XS::PV (), # SQL_CHAR
60             Text::CSV_XS::NV (), # SQL_NUMERIC
61             Text::CSV_XS::NV (), # SQL_DECIMAL
62             Text::CSV_XS::IV (), # SQL_INTEGER
63             Text::CSV_XS::IV (), # SQL_SMALLINT
64             Text::CSV_XS::NV (), # SQL_FLOAT
65             Text::CSV_XS::NV (), # SQL_REAL
66             Text::CSV_XS::NV (), # SQL_DOUBLE
67             );
68              
69             our @ISA = qw( DBD::File::dr );
70              
71             our $imp_data_size = 0;
72             our $data_sources_attr = undef;
73              
74             sub connect {
75 259     259   841803 my ($drh, $dbname, $user, $auth, $attr) = @_;
76 259 50 33     2153 if ($attr && ref $attr eq "HASH") {
77             # Top-level aliasses
78 259         991 foreach my $key (grep { exists $attr->{$_} } @f_SHORT) {
  2331         7856  
79 3         5 my $f_key = "f_$key";
80 3 50       10 exists $attr->{$f_key} and next;
81 3         10 $attr->{$f_key} = delete $attr->{$key};
82             }
83 259         858 foreach my $key (grep { exists $attr->{$_} } @c_SHORT) {
  5698         9926  
84 3         5 my $c_key = "csv_$key";
85 3 50       7 exists $attr->{$c_key} and next;
86 3         6 $attr->{$c_key} = delete $attr->{$key};
87             }
88             }
89              
90 259         2733 my $dbh = $drh->DBD::File::dr::connect ($dbname, $user, $auth, $attr);
91 259 50       285192 $dbh and $dbh->{Active} = 1;
92 259         4734 $dbh;
93             } # connect
94              
95             # --- DATABASE -----------------------------------------------------------------
96              
97             package DBD::CSV::db;
98              
99 24     24   169 use strict;
  24         51  
  24         17273  
100              
101             our $imp_data_size = 0;
102             our @ISA = qw( DBD::File::db );
103              
104             sub set_versions {
105 259     259   13351 my $this = shift;
106 259         919 $this->{csv_version} = $DBD::CSV::VERSION;
107 259         853 return $this->SUPER::set_versions ();
108             } # set_versions
109              
110             my %csv_xs_attr;
111              
112             sub init_valid_attributes {
113 259     259   38231 my $dbh = shift;
114              
115             # Straight from Text::CSV_XS.pm
116 259         1892 my @xs_attr = @c_SHORT;
117 259         2927 @csv_xs_attr{@xs_attr} = ();
118             # Dynamically add "new" attributes - available in Text::CSV_XS-1.20
119 259 50       716 if (my @ka = eval { Text::CSV_XS->known_attributes }) {
  259         2772  
120 259 100       12109 for (grep { m/^[a-su-z]/ && !exists $csv_xs_attr{$_} } @ka) {
  8288         26135  
121 216         421 push @xs_attr => $_;
122 216         419 $csv_xs_attr{$_} = undef;
123             }
124             };
125              
126 259         2224 $dbh->{csv_xs_valid_attrs} = [ @xs_attr ];
127              
128 259         1055 $dbh->{csv_valid_attrs} = { map {("csv_$_" => 1 )} @xs_attr, qw(
  9022         21297  
129              
130             class tables in csv_in out csv_out skip_first_row
131              
132             null sep quote escape bom
133             )};
134              
135 259         1793 $dbh->{csv_readonly_attrs} = { };
136              
137 259         857 $dbh->{csv_meta} = "csv_tables";
138              
139 259         1437 return $dbh->SUPER::init_valid_attributes ();
140             } # init_valid_attributes
141              
142             sub get_csv_versions {
143 1     1   356 my ($dbh, $table) = @_;
144 1   50     6 $table ||= "";
145 1         1 my $class = $dbh->{ImplementorClass};
146 1         4 $class =~ s/::db$/::Table/;
147 1         1 my $meta;
148 1 50       3 $table and (undef, $meta) = $class->get_table_meta ($dbh, $table, 1);
149 1 50       2 unless ($meta) {
150 1         1 $meta = {};
151 1         7 $class->bootstrap_table_meta ($dbh, $meta, $table);
152             }
153 1         57 my $dvsn = eval { $meta->{csv_class}->VERSION (); };
  1         10  
154 1         1 my $dtype = $meta->{csv_class};
155 1 50       3 $dvsn and $dtype .= " ($dvsn)";
156 1         19 return sprintf "%s using %s", $dbh->{csv_version}, $dtype;
157             } # get_csv_versions
158              
159             sub get_info {
160 209     209   349806 my ($dbh, $info_type) = @_;
161 209         5446 require DBD::CSV::GetInfo;
162 209         920 my $v = $DBD::CSV::GetInfo::info{int ($info_type)};
163 209 50       905 ref $v eq "CODE" and $v = $v->($dbh);
164 209         622 return $v;
165             } # get_info
166              
167             sub type_info_all {
168             # my $dbh = shift;
169 1     1   6522 require DBD::CSV::TypeInfo;
170 1         11 return [@$DBD::CSV::TypeInfo::type_info_all];
171             } # type_info_all
172              
173             # --- STATEMENT ----------------------------------------------------------------
174              
175             package DBD::CSV::st;
176              
177 24     24   182 use strict;
  24         42  
  24         2264  
178              
179             our $imp_data_size = 0;
180             our @ISA = qw( DBD::File::st );
181              
182             package DBD::CSV::Statement;
183              
184 24     24   155 use strict;
  24         76  
  24         620  
185 24     24   109 use Carp;
  24         64  
  24         2999  
186              
187             our @ISA = qw( DBD::File::Statement );
188              
189             package DBD::CSV::Table;
190              
191 24     24   136 use strict;
  24         34  
  24         595  
192 24     24   111 use Carp;
  24         46  
  24         41768  
193              
194             our @ISA = qw( DBD::File::Table );
195              
196             my %compat_map;
197              
198             { my %class_mapped;
199              
200             sub _register_compat_map {
201 6305     6305   10026 my $class = shift;
202              
203 6305         8705 my $x = 0;
204 6305 100       13727 if (!%compat_map) {
205 23         366 $compat_map{$_} = "f_$_" for @f_SHORT;
206 23         609 $compat_map{$_} = "csv_$_" for @c_SHORT;
207 23         59 $x++;
208             }
209 6305 100 66     27248 if ($class and !$class_mapped{$class}++ and
      100        
210 25         247 my @ka = eval { $class->known_attributes }) {
211             # exclude types
212 23         1631 $compat_map{$_} = "csv_$_" for grep m/^[a-su-z]/ => @ka;
213 23         57 $x++;
214             }
215 6305 100       15091 if ($x) {
216 23         324 __PACKAGE__->register_compat_map (\%compat_map);
217             }
218             } # _register_compat_map
219             }
220              
221             #sub DESTROY {
222             # my $self = shift or return;
223             #
224             # $self->{meta} and delete $self->{meta}{csv_in};
225             # } # DESTROY
226              
227             sub bootstrap_table_meta {
228 5992     5992   5725997 my ($self, $dbh, $meta, $table) = @_;
229 5992   100     53530 $meta->{csv_class} ||= $dbh->{csv_class} || "Text::CSV_XS";
      66        
230 5992   100     30892 $meta->{csv_eol} ||= $dbh->{csv_eol} || "\r\n";
      66        
231              
232 5992         14990 _register_compat_map ($meta->{csv_class});
233              
234             exists $meta->{csv_skip_first_row} or
235 5992 100       18295 $meta->{csv_skip_first_row} = $dbh->{csv_skip_first_row};
236             exists $meta->{csv_bom} or
237 5992 50       20907 $meta->{csv_bom} = exists $dbh->{bom} ? $dbh->{bom} : $dbh->{csv_bom};
    100          
238 5992         17008 $self->SUPER::bootstrap_table_meta ($dbh, $meta, $table);
239             } # bootstrap_table_meta
240              
241             sub init_table_meta {
242 293     293   261966 my ($self, $dbh, $meta, $table) = @_;
243              
244 293         1165 _register_compat_map ($meta->{csv_class});
245              
246 293         1681 $self->SUPER::init_table_meta ($dbh, $table, $meta);
247              
248 293   66     2428 my $csv_in = $meta->{csv_in} || $dbh->{csv_csv_in};
249 293 100       945 unless ($csv_in) {
250 275         1380 my %opts = ( binary => 1, auto_diag => 1 );
251              
252             # Allow specific Text::CSV_XS options
253 275         473 foreach my $attr (@{$dbh->{csv_xs_valid_attrs}}) {
  275         1006  
254 6293 100       10717 $attr eq "eol" and next; # Handles below
255 6018 100       14367 exists $dbh->{"csv_$attr"} and $opts{$attr} = $dbh->{"csv_$attr"};
256             }
257             $dbh->{csv_null} || $meta->{csv_null} and
258             $opts{Text::CSV_XS->version < 1.18 ? "always_quote" : "quote_empty"} =
259 275 50 66     1613 $opts{blank_is_undef} = 1;
    100          
260              
261 275         809 my $class = $meta->{csv_class};
262 275         699 my $eol = $meta->{csv_eol};
263 275 50       1822 $eol =~ m/^\A(?:[\r\n]|\r\n)\Z/ or $opts{eol} = $eol;
264 275         1656 for ([ "sep", ',' ],
265             [ "quote", '"' ],
266             [ "escape", '"' ],
267             ) {
268 825         2053 my ($attr, $def) = ($_->[0]."_char", $_->[1]);
269             $opts{$attr} =
270             exists $meta->{$attr} ? $meta->{$attr} :
271 825 100       3477 exists $dbh->{"csv_$attr"} ? $dbh->{"csv_$attr"} : $def;
    50          
272             }
273 275 50       3394 $meta->{csv_in} = $class->new (\%opts) or
274             $class->error_diag;
275 273         69055 $opts{eol} = $eol;
276 273 50       1060 $meta->{csv_out} = $class->new (\%opts) or
277             $class->error_diag;
278             }
279             } # init_table_meta
280              
281             sub table_meta_attr_changed {
282 20     20   4531 my ($class, $meta, $attr, $value) = @_;
283              
284 20         47 _register_compat_map ($meta->{csv_class});
285              
286 20         39 (my $csv_attr = $attr) =~ s/^csv_//;
287 20 100       40 if (exists $csv_xs_attr{$csv_attr}) {
288 3         6 for ("csv_in", "csv_out") {
289             exists $meta->{$_} && exists $meta->{$_}{$csv_attr} and
290 6 50 33     35 $meta->{$_}{$csv_attr} = $value;
291             }
292             }
293              
294 20         52 $class->SUPER::table_meta_attr_changed ($meta, $attr, $value);
295             } # table_meta_attr_changed
296              
297             sub open_data {
298 437     437   1638871 my ($self, $meta, $attrs, $flags) = @_;
299 437         2094 $self->SUPER::open_file ($meta, $attrs, $flags);
300              
301 427 50 33     162892 if ($meta && $meta->{fh}) {
302 427         1453 $attrs->{csv_csv_in} = $meta->{csv_in};
303 427         1347 $attrs->{csv_csv_out} = $meta->{csv_out};
304 427 100       1592 if (my $types = $meta->{types}) {
305             # XXX $meta->{types} is nowhere assigned and should better $meta->{csv_types}
306             # The 'types' array contains DBI types, but we need types
307             # suitable for Text::CSV_XS.
308 2         5 my $t = [];
309 2         4 for (@{$types}) {
  2         8  
310 6 100 66     27 $_ = $_
311             ? $DBD::CSV::dr::CSV_TYPES[$_ + 6] || Text::CSV_XS::PV ()
312             : Text::CSV_XS::PV ();
313 6         22 push @$t, $_;
314             }
315 2         5 $meta->{types} = $t;
316             }
317 427 100       1404 if (!$flags->{createMode}) {
318 397         649 my $array;
319             my $skipRows = defined $meta->{skip_rows}
320             ? $meta->{skip_rows}
321             : defined $meta->{csv_skip_first_row}
322             ? 1
323 397 100       1972 : exists $meta->{col_names} ? 0 : 1;
    50          
    100          
324             defined $meta->{skip_rows} or
325 397 100       1413 $meta->{skip_rows} = $skipRows;
326 397 50       1203 if ($meta->{csv_bom}) {
327             my @hdr = $attrs->{csv_csv_in}->header ($meta->{fh}) or
328 0 0       0 croak "Failed using the header row: ".$attrs->{csv_csv_in}->error_diag;
329 0   0     0 $meta->{col_names} ||= \@hdr;
330 0 0       0 $skipRows and $skipRows = 0;
331             }
332 397 100       1109 if ($skipRows--) {
333             $array = $attrs->{csv_csv_in}->getline ($meta->{fh}) or
334 391 50       25483 croak "Missing first row due to ".$attrs->{csv_csv_in}->error_diag;
335 391 50       7646 unless ($meta->{raw_header}) {
336 391         2137 s/\W/_/g for @$array;
337             }
338             defined $meta->{col_names} or
339 391 100       1622 $meta->{col_names} = $array;
340 391         1378 while ($skipRows--) {
341 12         49 $attrs->{csv_csv_in}->getline ($meta->{fh});
342             }
343             }
344             # lockMode is set 1 for DELETE, INSERT or UPDATE
345             # no other case need seeking
346             $flags->{lockMode} and # $meta->{fh}->can ("tell") and
347 397 100       1679 $meta->{first_row_pos} = $meta->{fh}->tell ();
348             exists $meta->{col_names} and
349 397 50       2051 $array = $meta->{col_names};
350 397 100 66     1257 if (!$meta->{col_names} || !@{$meta->{col_names}}) {
351             # No column names given; fetch first row and create default
352             # names.
353             my $ar = $meta->{cached_row} =
354 1         55 $attrs->{csv_csv_in}->getline ($meta->{fh});
355 1         3 $array = $meta->{col_names};
356 1         4 push @$array, map { "col$_" } 0 .. $#$ar;
  4         9  
357             }
358             }
359             }
360             } # open_file
361              
362 24     24   189 no warnings 'once';
  24         39  
  24         2079  
363             $DBI::VERSION < 1.623 and
364             *open_file = \&open_data;
365 24     24   127 use warnings;
  24         40  
  24         15994  
366              
367             sub _csv_diag {
368 2     2   5 my @diag = $_[0]->error_diag;
369 2         37 for (2, 3) {
370 4 50       11 defined $diag[$_] or $diag[$_] = "?";
371             }
372 2         7 return @diag;
373             } # _csv_diag
374              
375             sub fetch_row {
376 1177     1177   336515 my ($self, $data) = @_;
377              
378 1177         2283 my $tbl = $self->{meta};
379              
380             exists $tbl->{cached_row} and
381 1177 100       3175 return $self->{row} = delete $tbl->{cached_row};
382              
383             my $csv = $self->{csv_csv_in} or
384 1176 50       3135 return do { $data->set_err ($DBI::stderr, "Fetch from undefined handle"); undef };
  0         0  
  0         0  
385              
386 1176         1900 my $fields = eval { $csv->getline ($tbl->{fh}) };
  1176         19486  
387 1176 100       10362 unless ($fields) {
388 285 100       1702 $csv->eof and return;
389              
390 2         17 my @diag = _csv_diag ($csv);
391 2 50       20 $diag[0] == 2012 and return; # Also EOF (broken in Text::CSV_XS-1.10)
392              
393 2         4 my $file = $tbl->{f_fqfn};
394 2         587 croak "Error $diag[0] while reading file $file: $diag[1] \@ line $diag[3] pos $diag[2]";
395             }
396 891         2313 @$fields < @{$tbl->{col_names}} and
397 891 50       1351 push @$fields, (undef) x (@{$tbl->{col_names}} - @$fields);
  0         0  
398 891 50       3491 $self->{row} = (@$fields ? $fields : undef);
399             } # fetch_row
400              
401             sub push_row {
402 189     189   67807 my ($self, $data, $fields) = @_;
403 189         341 my $tbl = $self->{meta};
404 189         348 my $csv = $self->{csv_csv_out};
405 189         284 my $fh = $tbl->{fh};
406              
407 189 50       1794 unless ($csv->print ($fh, $fields)) {
408 0         0 my @diag = _csv_diag ($csv);
409 0         0 my $file = $tbl->{f_fqfn};
410 0         0 return do { $data->set_err ($DBI::stderr,
  0         0  
411 0         0 "Error $diag[0] while writing file $file: $diag[1] \@ line $diag[3] pos $diag[2]"); undef };
412             }
413 189         2353 1;
414             } # push_row
415              
416 24     24   180 no warnings 'once';
  24         58  
  24         1586  
417             *push_names = \&push_row;
418 24     24   186 use warnings;
  24         166  
  24         2093  
419              
420             1;
421              
422             __END__
423              
424             =head1 NAME
425              
426             DBD::CSV - DBI driver for CSV files
427              
428             =head1 SYNOPSIS
429              
430             use DBI;
431             # See "Creating database handle" below
432             $dbh = DBI->connect ("dbi:CSV:", undef, undef, {
433             f_ext => ".csv/r",
434             RaiseError => 1,
435             }) or die "Cannot connect: $DBI::errstr";
436              
437             # Simple statements
438             $dbh->do ("CREATE TABLE foo (id INTEGER, name CHAR (10))");
439              
440             # Selecting
441             my $sth = $dbh->prepare ("select * from foo");
442             $sth->execute;
443             $sth->bind_columns (\my ($id, $name));
444             while ($sth->fetch) {
445             print "id: $id, name: $name\n";
446             }
447              
448             # Updates
449             my $sth = $dbh->prepare ("UPDATE foo SET name = ? WHERE id = ?");
450             $sth->execute ("DBI rocks!", 1);
451             $sth->finish;
452              
453             $dbh->disconnect;
454              
455             =head1 DESCRIPTION
456              
457             The DBD::CSV module is yet another driver for the DBI (Database independent
458             interface for Perl). This one is based on the SQL "engine" SQL::Statement
459             and the abstract DBI driver DBD::File and implements access to so-called
460             CSV files (Comma Separated Values). Such files are often used for exporting
461             MS Access and MS Excel data.
462              
463             See L<DBI> for details on DBI, L<SQL::Statement> for details on
464             SQL::Statement and L<DBD::File> for details on the base class DBD::File.
465              
466             =head2 Prerequisites
467              
468             The only system dependent feature that DBD::File uses, is the C<flock ()>
469             function. Thus the module should run (in theory) on any system with
470             a working C<flock ()>, in particular on all Unix machines and on Windows
471             NT. Under Windows 95 and MacOS the use of C<flock ()> is disabled, thus
472             the module should still be usable.
473              
474             Unlike other DBI drivers, you don't need an external SQL engine or a
475             running server. All you need are the following Perl modules, available
476             from any CPAN mirror, for example
477              
478             http://search.cpan.org/
479              
480             =over 4
481              
482             =item DBI
483             X<DBI>
484              
485             A recent version of the L<DBI> (Database independent interface for Perl).
486             See below why.
487              
488             =item DBD::File
489             X<DBD::File>
490              
491             This is the base class for DBD::CSV, and it is part of the DBI
492             distribution. As DBD::CSV requires a matching version of L<DBD::File>
493             which is (partly) developed by the same team that maintains
494             DBD::CSV. See META.json or Makefile.PL for the minimum versions.
495              
496             =item SQL::Statement
497             X<SQL::Statement>
498              
499             A simple SQL engine. This module defines all of the SQL syntax for
500             DBD::CSV, new SQL support is added with each release so you should
501             look for updates to SQL::Statement regularly.
502              
503             It is possible to run C<DBD::CSV> without this module if you define
504             the environment variable C<$DBI_SQL_NANO> to 1. This will reduce the
505             SQL support a lot though. See L<DBI::SQL::Nano> for more details. Note
506             that the test suite does only test in this mode in the development
507             environment.
508              
509             =item Text::CSV_XS
510             X<Text::CSV_XS>
511              
512             This module is used to read and write rows in a CSV file.
513              
514             =back
515              
516             =head2 Installation
517              
518             Installing this module (and the prerequisites from above) is quite simple.
519             The simplest way is to install the bundle:
520              
521             $ cpan Bundle::DBD::CSV
522              
523             Alternatively, you can name them all
524              
525             $ cpan Text::CSV_XS DBI DBD::CSV
526              
527             or even trust C<cpan> to resolve all dependencies for you:
528              
529             $ cpan DBD::CSV
530              
531             If you cannot, for whatever reason, use cpan, fetch all modules from
532             CPAN, and build with a sequence like:
533              
534             gzip -d < DBD-CSV-0.40.tgz | tar xf -
535              
536             (this is for Unix users, Windows users would prefer WinZip or something
537             similar) and then enter the following:
538              
539             cd DBD-CSV-0.40
540             perl Makefile.PL
541             make test
542              
543             If any tests fail, let us know. Otherwise go on with
544              
545             make install UNINST=1
546              
547             Note that you almost definitely need root or administrator permissions.
548             If you don't have them, read the ExtUtils::MakeMaker man page for details
549             on installing in your own directories. L<ExtUtils::MakeMaker>.
550              
551             =head2 Supported SQL Syntax
552              
553             All SQL processing for DBD::CSV is done by SQL::Statement. See
554             L<SQL::Statement> for more specific information about its feature set.
555             Features include joins, aliases, built-in and user-defined functions,
556             and more. See L<SQL::Statement::Syntax> for a description of the SQL
557             syntax supported in DBD::CSV.
558              
559             Table- and column-names are case insensitive unless quoted. Column names
560             will be sanitized unless L</raw_header> is true.
561              
562             =head1 Using DBD::CSV with DBI
563              
564             For most things, DBD-CSV operates the same as any DBI driver.
565             See L<DBI> for detailed usage.
566              
567             =head2 Creating a database handle (connect)
568              
569             Creating a database handle usually implies connecting to a database server.
570             Thus this command reads
571              
572             use DBI;
573             my $dbh = DBI->connect ("dbi:CSV:", "", "", {
574             f_dir => "/home/user/folder",
575             });
576              
577             The directory tells the driver where it should create or open tables (a.k.a.
578             files). It defaults to the current directory, so the following are equivalent:
579              
580             $dbh = DBI->connect ("dbi:CSV:");
581             $dbh = DBI->connect ("dbi:CSV:", undef, undef, { f_dir => "." });
582             $dbh = DBI->connect ("dbi:CSV:f_dir=.");
583              
584             We were told, that VMS might - for whatever reason - require:
585              
586             $dbh = DBI->connect ("dbi:CSV:f_dir=");
587              
588             The preferred way of passing the arguments is by driver attributes:
589              
590             # specify most possible flags via driver flags
591             $dbh = DBI->connect ("dbi:CSV:", undef, undef, {
592             f_schema => undef,
593             f_dir => "data",
594             f_dir_search => [],
595             f_ext => ".csv/r",
596             f_lock => 2,
597             f_encoding => "utf8",
598              
599             csv_eol => "\r\n",
600             csv_sep_char => ",",
601             csv_quote_char => '"',
602             csv_escape_char => '"',
603             csv_class => "Text::CSV_XS",
604             csv_null => 1,
605             csv_bom => 0,
606             csv_tables => {
607             syspwd => {
608             sep_char => ":",
609             quote_char => undef,
610             escape_char => undef,
611             file => "/etc/passwd",
612             col_names => [qw( login password
613             uid gid realname
614             directory shell )],
615             },
616             },
617              
618             RaiseError => 1,
619             PrintError => 1,
620             FetchHashKeyName => "NAME_lc",
621             }) or die $DBI::errstr;
622              
623             but you may set these attributes in the DSN as well, separated by semicolons.
624             Pay attention to the semi-colon for C<csv_sep_char> (as seen in many CSV
625             exports from MS Excel) is being escaped in below example, as is would
626             otherwise be seen as attribute separator:
627              
628             $dbh = DBI->connect (
629             "dbi:CSV:f_dir=$ENV{HOME}/csvdb;f_ext=.csv;f_lock=2;" .
630             "f_encoding=utf8;csv_eol=\n;csv_sep_char=\\;;" .
631             "csv_quote_char=\";csv_escape_char=\\;csv_class=Text::CSV_XS;" .
632             "csv_null=1") or die $DBI::errstr;
633              
634             Using attributes in the DSN is easier to use when the DSN is derived from an
635             outside source (environment variable, database entry, or configure file),
636             whereas specifying entries in the attribute hash is easier to read and to
637             maintain.
638              
639             The default value for C<csv_binary> is C<1> (True).
640              
641             The default value for C<csv_auto_diag> is <1>. Note that this might cause
642             trouble on perl versions older than 5.8.9, so up to and including perl
643             version 5.8.8 it might be required to use C<;csv_auto_diag=0> inside the
644             C<DSN> or C<csv_auto_diag => 0> inside the attributes.
645              
646             =head2 Creating and dropping tables
647              
648             You can create and drop tables with commands like the following:
649              
650             $dbh->do ("CREATE TABLE $table (id INTEGER, name CHAR (64))");
651             $dbh->do ("DROP TABLE $table");
652              
653             Note that currently only the column names will be stored and no other data.
654             Thus all other information including column type (INTEGER or CHAR (x), for
655             example), column attributes (NOT NULL, PRIMARY KEY, ...) will silently be
656             discarded. This may change in a later release.
657              
658             A drop just removes the file without any warning.
659              
660             See L<DBI> for more details.
661              
662             Table names cannot be arbitrary, due to restrictions of the SQL syntax.
663             I recommend that table names are valid SQL identifiers: The first
664             character is alphabetic, followed by an arbitrary number of alphanumeric
665             characters. If you want to use other files, the file names must start
666             with "/", "./" or "../" and they must not contain white space.
667              
668             =head2 Inserting, fetching and modifying data
669              
670             The following examples insert some data in a table and fetch it back:
671             First, an example where the column data is concatenated in the SQL string:
672              
673             $dbh->do ("INSERT INTO $table VALUES (1, ".
674             $dbh->quote ("foobar") . ")");
675              
676             Note the use of the quote method for escaping the word "foobar". Any
677             string must be escaped, even if it does not contain binary data.
678              
679             Next, an example using parameters:
680              
681             $dbh->do ("INSERT INTO $table VALUES (?, ?)", undef, 2,
682             "It's a string!");
683              
684             Note that you don't need to quote column data passed as parameters.
685             This version is particularly well designed for
686             loops. Whenever performance is an issue, I recommend using this method.
687              
688             You might wonder about the C<undef>. Don't wonder, just take it as it
689             is. :-) It's an attribute argument that I have never used and will be
690             passed to the prepare method as the second argument.
691              
692             To retrieve data, you can use the following:
693              
694             my $query = "SELECT * FROM $table WHERE id > 1 ORDER BY id";
695             my $sth = $dbh->prepare ($query);
696             $sth->execute ();
697             while (my $row = $sth->fetchrow_hashref) {
698             print "Found result row: id = ", $row->{id},
699             ", name = ", $row->{name};
700             }
701             $sth->finish ();
702              
703             Again, column binding works: The same example again.
704              
705             my $sth = $dbh->prepare (qq;
706             SELECT * FROM $table WHERE id > 1 ORDER BY id;
707             ;);
708             $sth->execute;
709             my ($id, $name);
710             $sth->bind_columns (undef, \$id, \$name);
711             while ($sth->fetch) {
712             print "Found result row: id = $id, name = $name\n";
713             }
714             $sth->finish;
715              
716             Of course you can even use input parameters. Here's the same example
717             for the third time:
718              
719             my $sth = $dbh->prepare ("SELECT * FROM $table WHERE id = ?");
720             $sth->bind_columns (undef, \$id, \$name);
721             for (my $i = 1; $i <= 2; $i++) {
722             $sth->execute ($id);
723             if ($sth->fetch) {
724             print "Found result row: id = $id, name = $name\n";
725             }
726             $sth->finish;
727             }
728              
729             See L<DBI> for details on these methods. See L<SQL::Statement> for
730             details on the WHERE clause.
731              
732             Data rows are modified with the UPDATE statement:
733              
734             $dbh->do ("UPDATE $table SET id = 3 WHERE id = 1");
735              
736             Likewise you use the DELETE statement for removing rows:
737              
738             $dbh->do ("DELETE FROM $table WHERE id > 1");
739              
740             =head2 Error handling
741              
742             In the above examples we have never cared about return codes. Of
743             course, this is not recommended. Instead we should have written (for
744             example):
745              
746             my $sth = $dbh->prepare ("SELECT * FROM $table WHERE id = ?") or
747             die "prepare: " . $dbh->errstr ();
748             $sth->bind_columns (undef, \$id, \$name) or
749             die "bind_columns: " . $dbh->errstr ();
750             for (my $i = 1; $i <= 2; $i++) {
751             $sth->execute ($id) or
752             die "execute: " . $dbh->errstr ();
753             $sth->fetch and
754             print "Found result row: id = $id, name = $name\n";
755             }
756             $sth->finish ($id) or die "finish: " . $dbh->errstr ();
757              
758             Obviously this is tedious. Fortunately we have DBI's I<RaiseError>
759             attribute:
760              
761             $dbh->{RaiseError} = 1;
762             $@ = "";
763             eval {
764             my $sth = $dbh->prepare ("SELECT * FROM $table WHERE id = ?");
765             $sth->bind_columns (undef, \$id, \$name);
766             for (my $i = 1; $i <= 2; $i++) {
767             $sth->execute ($id);
768             $sth->fetch and
769             print "Found result row: id = $id, name = $name\n";
770             }
771             $sth->finish ($id);
772             };
773             $@ and die "SQL database error: $@";
774              
775             This is not only shorter, it even works when using DBI methods within
776             subroutines.
777              
778             =head1 DBI database handle attributes
779              
780             =head2 Metadata
781              
782             The following attributes are handled by DBI itself and not by DBD::File,
783             thus they all work as expected:
784              
785             Active
786             ActiveKids
787             CachedKids
788             CompatMode (Not used)
789             InactiveDestroy
790             Kids
791             PrintError
792             RaiseError
793             Warn (Not used)
794              
795             The following DBI attributes are handled by DBD::File:
796              
797             =over 4
798              
799             =item AutoCommit
800             X<AutoCommit>
801              
802             Always on
803              
804             =item ChopBlanks
805             X<ChopBlanks>
806              
807             Works
808              
809             =item NUM_OF_FIELDS
810             X<NUM_OF_FIELDS>
811              
812             Valid after C<$sth-E<gt>execute>
813              
814             =item NUM_OF_PARAMS
815             X<NUM_OF_PARAMS>
816              
817             Valid after C<$sth-E<gt>prepare>
818              
819             =item NAME
820             X<NAME>
821              
822             =item NAME_lc
823             X<NAME_lc>
824              
825             =item NAME_uc
826             X<NAME_uc>
827              
828             Valid after C<$sth-E<gt>execute>; undef for Non-Select statements.
829              
830             =item NULLABLE
831             X<NULLABLE>
832              
833             Not really working. Always returns an array ref of one's, as DBD::CSV
834             does not verify input data. Valid after C<$sth-E<gt>execute>; undef for
835             non-Select statements.
836              
837             =back
838              
839             These attributes and methods are not supported:
840              
841             bind_param_inout
842             CursorName
843             LongReadLen
844             LongTruncOk
845              
846             =head1 DBD-CSV specific database handle attributes
847              
848             In addition to the DBI attributes, you can use the following dbh
849             attributes:
850              
851             =head2 DBD::File attributes
852              
853             =over 4
854              
855             =item f_dir
856             X<f_dir>
857              
858             This attribute is used for setting the directory where CSV files are
859             opened. Usually you set it in the dbh and it defaults to the current
860             directory ("."). However, it may be overridden in statement handles.
861              
862             =item f_dir_search
863             X<f_dir_search>
864              
865             This attribute optionally defines a list of extra directories to search
866             when opening existing tables. It should be an anonymous list or an array
867             reference listing all folders where tables could be found.
868              
869             my $dbh = DBI->connect ("dbi:CSV:", "", "", {
870             f_dir => "data",
871             f_dir_search => [ "ref/data", "ref/old" ],
872             f_ext => ".csv/r",
873             }) or die $DBI::errstr;
874              
875             =item f_ext
876             X<f_ext>
877              
878             This attribute is used for setting the file extension.
879              
880             =item f_schema
881             X<f_schema>
882              
883             This attribute allows you to set the database schema name. The default is
884             to use the owner of C<f_dir>. C<undef> is allowed, but not in the DSN part.
885              
886             my $dbh = DBI->connect ("dbi:CSV:", "", "", {
887             f_schema => undef,
888             f_dir => "data",
889             f_ext => ".csv/r",
890             }) or die $DBI::errstr;
891              
892             =item f_encoding
893             X<f_encoding>
894              
895             This attribute allows you to set the encoding of the data. With CSV, it is not
896             possible to set (and remember) the encoding on a column basis, but DBD::File
897             now allows the encoding to be set on the underlying file. If this attribute is
898             not set, or undef is passed, the file will be seen as binary.
899              
900             =item f_lock
901             X<f_lock>
902              
903             With this attribute you can specify a locking mode to be used (if locking is
904             supported at all) for opening tables. By default, tables are opened with a
905             shared lock for reading, and with an exclusive lock for writing. The
906             supported modes are:
907              
908             =over 2
909              
910             =item 0
911             X<0>
912              
913             Force no locking at all.
914              
915             =item 1
916             X<1>
917              
918             Only shared locks will be used.
919              
920             =item 2
921             X<2>
922              
923             Only exclusive locks will be used.
924              
925             =back
926              
927             =back
928              
929             But see L<DBD::File/"KNOWN BUGS">.
930              
931             =head2 DBD::CSV specific attributes
932              
933             =over 4
934              
935             =item csv_class
936              
937             The attribute I<csv_class> controls the CSV parsing engine. This defaults
938             to C<Text::CSV_XS>, but C<Text::CSV> can be used in some cases, too.
939             Please be aware that C<Text::CSV> does not care about any edge case as
940             C<Text::CSV_XS> does and that C<Text::CSV> is probably about 100 times
941             slower than C<Text::CSV_XS>.
942              
943             In order to use the specified class other than C<Text::CSV_XS>, it needs
944             to be loaded before use. C<DBD::CSV> does not C<require>/C<use> the
945             specified class itself.
946              
947             =back
948              
949             =head2 Text::CSV_XS specific attributes
950              
951             =over 4
952              
953             =item csv_eol
954             X<csv_eol>
955              
956             =item csv_sep_char
957             X<csv_sep_char>
958              
959             =item csv_quote_char
960             X<csv_quote_char>
961              
962             =item csv_escape_char
963             X<csv_escape_char>
964              
965             =item csv_csv
966             X<csv_csv>
967              
968             The attributes I<csv_eol>, I<csv_sep_char>, I<csv_quote_char> and
969             I<csv_escape_char> are corresponding to the respective attributes of the
970             I<csv_class> (usually Text::CSV_CS) object. You may want to set these
971             attributes if you have unusual CSV files like F</etc/passwd> or MS Excel
972             generated CSV files with a semicolon as separator. Defaults are
973             C<\015\012>", C<,>, C<"> and C<">, respectively.
974              
975             The I<csv_eol> attribute defines the end-of-line pattern, which is better
976             known as a record separator pattern since it separates records. The default
977             is windows-style end-of-lines C<\015\012> for output (writing) and unset for
978             input (reading), so if on unix you may want to set this to newline (C<\n>)
979             like this:
980              
981             $dbh->{csv_eol} = "\n";
982              
983             It is also possible to use multi-character patterns as record separators.
984             For example this file uses newlines as field separators (sep_char) and
985             the pattern "\n__ENDREC__\n" as the record separators (eol):
986              
987             name
988             city
989             __ENDREC__
990             joe
991             seattle
992             __ENDREC__
993             sue
994             portland
995             __ENDREC__
996              
997             To handle this file, you'd do this:
998              
999             $dbh->{eol} = "\n__ENDREC__\n" ,
1000             $dbh->{sep_char} = "\n"
1001              
1002             The attributes are used to create an instance of the class I<csv_class>,
1003             by default Text::CSV_XS. Alternatively you may pass an instance as
1004             I<csv_csv>, the latter takes precedence. Note that the I<binary>
1005             attribute I<must> be set to a true value in that case.
1006              
1007             Additionally you may overwrite these attributes on a per-table base in
1008             the I<csv_tables> attribute.
1009              
1010             =item csv_null
1011             X<csv_null>
1012              
1013             With this option set, all new statement handles will set C<always_quote>
1014             and C<blank_is_undef> in the CSV parser and writer, so it knows how to
1015             distinguish between the empty string and C<undef> or C<NULL>. You cannot
1016             reset it with a false value. You can pass it to connect, or set it later:
1017              
1018             $dbh = DBI->connect ("dbi:CSV:", "", "", { csv_null => 1 });
1019              
1020             $dbh->{csv_null} = 1;
1021              
1022             =item csv_bom
1023             X<csv_bom>
1024              
1025             With this option set, the CSV parser will try to detect BOM (Byte Order Mark)
1026             in the header line. This requires L<Text::CSV_XS> version 1.22 or higher.
1027              
1028             $dbh = DBI->connect ("dbi:CSV:", "", "", { csv_bom => 1 });
1029              
1030             $dbh->{csv_bom} = 1;
1031              
1032             =item csv_tables
1033             X<csv_tables>
1034              
1035             This hash ref is used for storing table dependent metadata. For any
1036             table it contains an element with the table name as key and another
1037             hash ref with the following attributes:
1038              
1039             =over 4
1040              
1041             =item o
1042              
1043             All valid attributes to the CSV parsing module. Any of them can optionally
1044             be prefixed with C<csv_>.
1045              
1046             =item o
1047              
1048             All attributes valid to DBD::File
1049              
1050             =back
1051              
1052             If you pass it C<f_file> or its alias C<file>, C<f_ext> has no effect, but
1053             C<f_dir> and C<f_encoding> still have.
1054              
1055             csv_tables => {
1056             syspwd => { # Table name
1057             csv_sep_char => ":", # Text::CSV_XS
1058             quote_char => undef, # Text::CSV_XS
1059             escape_char => undef, # Text::CSV_XS
1060             f_dir => "/etc", # DBD::File
1061             f_file => "passwd", # DBD::File
1062             col_names => # DBD::File
1063             [qw( login password uid gid realname directory shell )],
1064             },
1065             },
1066              
1067             =item csv_*
1068             X<csv_*>
1069              
1070             All other attributes that start with C<csv_> and are not described above
1071             will be passed to C<Text::CSV_XS> (without the C<csv_> prefix). These
1072             extra options are only likely to be useful for reading (select)
1073             handles. Examples:
1074              
1075             $dbh->{csv_allow_whitespace} = 1;
1076             $dbh->{csv_allow_loose_quotes} = 1;
1077             $dbh->{csv_allow_loose_escapes} = 1;
1078              
1079             See the C<Text::CSV_XS> documentation for the full list and the documentation.
1080              
1081             =back
1082              
1083             =head2 Driver specific attributes
1084              
1085             =over 4
1086              
1087             =item f_file
1088             X<f_file>
1089              
1090             The name of the file used for the table; defaults to
1091              
1092             "$dbh->{f_dir}/$table"
1093              
1094             =item eol
1095             X<eol>
1096              
1097             =item sep_char
1098             X<sep_char>
1099              
1100             =item quote_char
1101             X<quote_char>
1102              
1103             =item escape_char
1104             X<escape_char>
1105              
1106             =item class
1107             X<class>
1108              
1109             =item csv
1110             X<csv>
1111              
1112             These correspond to the attributes I<csv_eol>, I<csv_sep_char>,
1113             I<csv_quote_char>, I<csv_escape_char>, I<csv_class> and I<csv_csv>.
1114             The difference is that they work on a per-table basis.
1115              
1116             =item col_names
1117             X<col_names>
1118              
1119             =item skip_first_row
1120             X<skip_first_row>
1121              
1122             By default DBD::CSV assumes that column names are stored in the first row
1123             of the CSV file and sanitizes them (see C<raw_header> below). If this is
1124             not the case, you can supply an array ref of table names with the
1125             I<col_names> attribute. In that case the attribute I<skip_first_row> will
1126             be set to FALSE.
1127              
1128             If you supply an empty array ref, the driver will read the first row
1129             for you, count the number of columns and create column names like
1130             C<col0>, C<col1>, ...
1131              
1132             Note that column names that match reserved SQL words will cause unwanted
1133             and sometimes confusing errors. If your CSV has headers that match reserved
1134             words, you will require these two attributes.
1135              
1136             If C<test.csv> looks like
1137              
1138             select,from
1139             1,2
1140              
1141             the select query would result in C<select select, from from test;>, which
1142             obviously is illegal SQL.
1143              
1144             =item raw_header
1145             X<raw_header>
1146              
1147             Due to the SQL standard, field names cannot contain special characters
1148             like a dot (C<.>) or a space (C< >) unless the column names are quoted.
1149             Following the approach of mdb_tools, all these tokens are translated to an
1150             underscore (C<_>) when reading the first line of the CSV file, so all field
1151             names are 'sanitized'. If you do not want this to happen, set C<raw_header>
1152             to a true value and the entries in the first line of the CSV data will be
1153             used verbatim for column headers and field names. DBD::CSV cannot guarantee
1154             that any part in the toolchain will work if field names have those characters,
1155             and the chances are high that the SQL statements will fail.
1156              
1157             Currently, the sanitizing of headers is as simple as
1158              
1159             s/\W/_/g;
1160              
1161             Note that headers (column names) might be folded in other parts of the code
1162             stack, specifically SQL::Statement, whose docs mention:
1163              
1164             Wildcards are expanded to lower cased identifiers. This might
1165             confuse some people, but it was easier to implement.
1166              
1167             That means that in
1168              
1169             my $sth = $dbh->prepare ("select * from foo");
1170             $sth->execute;
1171             while (my $row = $sth->fetchrow_hashref) {
1172             say for keys %$row;
1173             }
1174              
1175             all keys will show as all lower case, regardless of the original header.
1176              
1177             =back
1178              
1179             It's strongly recommended to check the attributes supported by
1180             L<DBD::File/Metadata>.
1181              
1182             Example: Suppose you want to use F</etc/passwd> as a CSV file. :-)
1183             There simplest way is:
1184              
1185             use DBI;
1186             my $dbh = DBI->connect ("dbi:CSV:", undef, undef, {
1187             f_dir => "/etc",
1188             csv_sep_char => ":",
1189             csv_quote_char => undef,
1190             csv_escape_char => undef,
1191             });
1192             $dbh->{csv_tables}{passwd} = {
1193             col_names => [qw( login password uid gid realname
1194             directory shell )];
1195             };
1196             $sth = $dbh->prepare ("SELECT * FROM passwd");
1197              
1198             Another possibility where you leave all the defaults as they are and
1199             override them on a per table basis:
1200              
1201             require DBI;
1202             my $dbh = DBI->connect ("dbi:CSV:");
1203             $dbh->{csv_tables}{passwd} = {
1204             eol => "\n",
1205             sep_char => ":",
1206             quote_char => undef,
1207             escape_char => undef,
1208             f_file => "/etc/passwd",
1209             col_names => [qw( login password uid gid
1210             realname directory shell )],
1211             };
1212             $sth = $dbh->prepare ("SELECT * FROM passwd");
1213              
1214             =head2 Driver private methods
1215              
1216             These methods are inherited from DBD::File:
1217              
1218             =over 4
1219              
1220             =item data_sources
1221             X<data_sources>
1222              
1223             The C<data_sources> method returns a list of sub-directories of the current
1224             directory in the form "dbi:CSV:directory=$dirname".
1225              
1226             If you want to read the sub-directories of another directory, use
1227              
1228             my $drh = DBI->install_driver ("CSV");
1229             my @list = $drh->data_sources (f_dir => "/usr/local/csv_data");
1230              
1231             =item list_tables
1232             X<list_tables>
1233              
1234             This method returns a list of file-names inside $dbh->{directory}.
1235             Example:
1236              
1237             my $dbh = DBI->connect ("dbi:CSV:directory=/usr/local/csv_data");
1238             my @list = $dbh->func ("list_tables");
1239              
1240             Note that the list includes all files contained in the directory, even
1241             those that have non-valid table names, from the view of SQL. See
1242             L<Creating and dropping tables> above.
1243              
1244             =back
1245              
1246             =head1 KNOWN ISSUES
1247              
1248             =over 4
1249              
1250             =item *
1251              
1252             The module is using flock () internally. However, this function is not
1253             available on some platforms. Use of flock () is disabled on MacOS and
1254             Windows 95: There's no locking at all (perhaps not so important on
1255             these operating systems, as they are for single users anyways).
1256              
1257             =back
1258              
1259             =head1 TODO
1260              
1261             =over 4
1262              
1263             =item Tests
1264             X<Tests>
1265              
1266             Aim for a full 100% code coverage
1267              
1268             - eol Make tests for different record separators.
1269             - csv_xs Test with a variety of combinations for
1270             sep_char, quote_char, and escape_char testing
1271             - quoting $dbh->do ("drop table $_") for DBI-tables ();
1272             - errors Make sure that all documented exceptions are tested.
1273             . write to write-protected file
1274             . read from badly formatted csv
1275             . pass bad arguments to csv parser while fetching
1276              
1277             Add tests that specifically test DBD::File functionality where
1278             that is useful.
1279              
1280             =item RT
1281             X<RT>
1282              
1283             Attack all open DBD::CSV bugs in RT
1284              
1285             =item CPAN::Forum
1286             X<CPAN::Forum>
1287              
1288             Attack all items in http://www.cpanforum.com/dist/DBD-CSV
1289              
1290             =item Documentation
1291             X<Documentation>
1292              
1293             Expand on error-handling, and document all possible errors.
1294             Use Text::CSV_XS::error_diag () wherever possible.
1295              
1296             =item Debugging
1297             X<Debugging>
1298              
1299             Implement and document dbd_verbose.
1300              
1301             =item Data dictionary
1302             X<Data dictionary>
1303              
1304             Investigate the possibility to store the data dictionary in a file like
1305             .sys$columns that can store the field attributes (type, key, nullable).
1306              
1307             =item Examples
1308             X<Examples>
1309              
1310             Make more real-life examples from the docs in examples/
1311              
1312             =back
1313              
1314             =head1 SEE ALSO
1315              
1316             L<DBI>, L<Text::CSV_XS>, L<SQL::Statement>, L<DBI::SQL::Nano>
1317              
1318             For help on the use of DBD::CSV, see the DBI users mailing list:
1319              
1320             http://lists.cpan.org/showlist.cgi?name=dbi-users
1321              
1322             For general information on DBI see
1323              
1324             http://dbi.perl.org/ and http://faq.dbi-support.com/
1325              
1326             =head1 AUTHORS and MAINTAINERS
1327              
1328             This module is currently maintained by
1329              
1330             H.Merijn Brand <h.m.brand@xs4all.nl>
1331              
1332             in close cooperation with and help from
1333              
1334             Jens Rehsack <sno@NetBSD.org>
1335              
1336             The original author is Jochen Wiedmann.
1337             Previous maintainer was Jeff Zucker
1338              
1339             =head1 COPYRIGHT AND LICENSE
1340              
1341             Copyright (C) 2009-2025 by H.Merijn Brand
1342             Copyright (C) 2004-2009 by Jeff Zucker
1343             Copyright (C) 1998-2004 by Jochen Wiedmann
1344              
1345             All rights reserved.
1346              
1347             You may distribute this module under the terms of either the GNU
1348             General Public License or the Artistic License, as specified in
1349             the Perl README file.
1350              
1351             =cut