Author: REHSACK
Date: Fri May 28 10:53:32 2010
New Revision: 14080

Modified:
   dbi/trunk/Changes
   dbi/trunk/lib/DBD/DBM.pm
   dbi/trunk/lib/DBD/File.pm
   dbi/trunk/t/49dbd_file.t

Log:
Fix issues of DBD::File introduced during refactoring found by DBD::CSV tests


Modified: dbi/trunk/Changes
==============================================================================
--- dbi/trunk/Changes   (original)
+++ dbi/trunk/Changes   Fri May 28 10:53:32 2010
@@ -26,6 +26,10 @@
     resources (Jens Rehsack)
   Changes to DBD::File for better English and hopefully better
     explanation (Martin J. Evans)
+  Update documentation of DBD::DBM to cover current implementation,
+    tried to explain some things better and changes most examples to
+    preferred style of Merijn and myself (Jens Rehsack)
+  DBD::DBM fixes found during tests (Jens Rehsack)
 
 =head2 Changes in DBI 1.611 (svn r13935) 29th April 2010
 

Modified: dbi/trunk/lib/DBD/DBM.pm
==============================================================================
--- dbi/trunk/lib/DBD/DBM.pm    (original)
+++ dbi/trunk/lib/DBD/DBM.pm    Fri May 28 10:53:32 2010
@@ -325,12 +325,9 @@
     return $tbl;
 }
 
-sub init_table_meta ($$$$$)
+sub bootstrap_table_meta
 {
-    my ( $self, $dbh, $table, $file_is_table, $quoted ) = @_;
-    defined $dbh->{f_meta}->{$table} and "HASH" eq ref $dbh->{f_meta}->{$table}
-      or $dbh->{f_meta}->{$table} = {};
-    my $meta = $dbh->{f_meta}->{$table};
+    my ( $self, $dbh, $meta, $table ) = @_;
 
     $meta->{dbm_type} ||= $dbh->{dbm_type} || 'SDBM_File';
     $meta->{dbm_mldbm} ||= $dbh->{dbm_mldbm} if ( $dbh->{dbm_mldbm} );
@@ -362,6 +359,13 @@
         $meta->{f_ext} = $ext if ( defined($ext) );
     }
 
+    $self->SUPER::bootstrap_table_meta( $dbh, $meta, $table );
+}
+
+sub init_table_meta
+{
+    my ( $self, $dbh, $meta, $table ) = @_;
+
     unless ( defined( $meta->{dbm_tietype} ) )
     {
         my $tie_type = $meta->{dbm_type};
@@ -390,18 +394,7 @@
         $meta->{col_names} = $dbh->{dbm_cols} if ( defined( $dbh->{dbm_cols} ) 
);
     }
 
-    $self->SUPER::init_table_meta( $dbh, $table, $file_is_table, $quoted );
-}
-
-sub default_table_meta ($$$)
-{
-    my ( $self, $dbh, $table ) = @_;
-    my $meta = $self->SUPER::default_table_meta( $dbh, $table );
-
-    $meta->{dbm_type} = $dbh->{dbm_type} || 'SDBM_File';
-    $meta->{dbm_mldbm} = $dbh->{dbm_mldbm} if ( $dbh->{dbm_mldbm} );
-
-    return $meta;
+    $self->SUPER::init_table_meta( $dbh, $table );
 }
 
 sub open_file

Modified: dbi/trunk/lib/DBD/File.pm
==============================================================================
--- dbi/trunk/lib/DBD/File.pm   (original)
+++ dbi/trunk/lib/DBD/File.pm   Fri May 28 10:53:32 2010
@@ -25,7 +25,6 @@
 
 use DBI ();
 require DBI::SQL::Nano;
-require File::Spec;
 
 package DBD::File;
 
@@ -114,6 +113,8 @@
            }
        }
     $this->STORE (Active => 1);
+    $this->STORE (sql_identifier_case => 2); # SQL_IC_LOWER
+    $this->STORE (sql_quoted_identifier_case => 3); # SQL_IC_SENSITIVE
     $this->func ("set_versions");
     return $this;
     } # connect
@@ -167,6 +168,8 @@
 
 use strict;
 use Carp;
+require File::Spec;
+require Cwd;
 
 $DBD::File::db::imp_data_size = 0;
 
@@ -193,8 +196,8 @@
 
        if ( $dbh->{sql_handler} eq "SQL::Statement" and
             $dbh->{sql_statement_version} > 1) {
-           my $parser = $dbh->{csv_sql_parser_object};
-           $parser ||= eval { $dbh->func ("cache_sql_parser_object") };
+           my $parser = $dbh->{sql_parser_object};
+           $parser ||= eval { $dbh->func ("sql_parser_object") };
            if ($@) {
                $stmt = eval { $class->new ($statement) };
                }
@@ -237,24 +240,43 @@
     my $sth = shift;
 
     $sth->{f_valid_attrs} = {
-       f_version  => 1, # DBD::File version
-       f_dir      => 1, # base directory
-       f_ext      => 1, # file extension
-       f_schema   => 1, # schema name
-       f_tables   => 1, # base directory
-       f_lock     => 1, # Table locking mode
-       f_encoding => 1, # Encoding of the file
+       f_version        => 1, # DBD::File version
+       f_dir            => 1, # base directory
+       f_ext            => 1, # file extension
+       f_schema         => 1, # schema name
+       f_meta           => 1, # meta data for tables
+       f_lock           => 1, # Table locking mode
+       f_encoding       => 1, # Encoding of the file
+       f_readonly_attrs => 1, # File readonly attributes
        };
     $sth->{sql_valid_attrs} = {
-       sql_handler           => 1, # Nano or S:S
-       sql_nano_version      => 1, # Nano version
-       sql_statement_version => 1, # S:S version
+       sql_handler                => 1, # Nano or S:S
+       sql_nano_version           => 1, # Nano version
+       sql_statement_version      => 1, # S:S version
+       sql_quoted_identifier_case => 1, # case for quoted identifiers
+       sql_identifier_case        => 1, # case for non-quoted identifiers
+       sql_parser_object          => 1, # SQL::Parser instance
+       sql_readonly_attrs         => 1, # SQL readonly attributes
+       };
+    $sth->{f_readonly_attrs} = {
+       f_version        => 1, # DBD::File version
+       f_valid_attrs    => 1, # File valid attributes
+       f_readonly_attrs => 1, # File readonly attributes
+       };
+    $sth->{sql_readonly_attrs} = {
+       sql_handler                => 1, # Nano or S:S
+       sql_nano_version           => 1, # Nano version
+       sql_statement_version      => 1, # S:S version
+       sql_quoted_identifier_case => 1, # case for quoted identifiers
+       sql_parser_object          => 1, # SQL::Parser instance
+       sql_valid_attrs            => 1, # SQL valid attributes
+       sql_readonly_attrs         => 1, # SQL readonly attributes
        };
 
     return $sth;
     } # init_valid_attributes
 
-sub cache_sql_parser_object
+sub sql_parser_object
 {
     my $dbh    = shift;
     my $parser = {
@@ -265,7 +287,7 @@
     my $sql_flags = $dbh->FETCH ("sql_flags") || {};
     %$parser = (%$parser, %$sql_flags);
     $parser = SQL::Parser->new ($parser->{dialect}, $parser);
-    $dbh->{csv_sql_parser_object} = $parser;
+    $dbh->{sql_parser_object} = $parser;
     return $parser;
     } # cache_sql_parser_object
 
@@ -321,11 +343,24 @@
        if ($attrib eq "f_dir") {
            -d $value or
                return $dbh->set_err ($DBI::stderr, "No such directory 
'$value'");
+           File::Spec->file_name_is_absolute ($value) or
+               $value = Cwd::abs_path ($value);
            }
        if ($attrib eq "f_ext") {
            $value eq "" || $value =~ m{^\.\w+(?:/[rR]*)?$} or
                carp "'$value' doesn't look like a valid file extension 
attribute\n";
            }
+       if (($attrib eq "sql_identifier_case" or $attrib eq 
"sql_quoted_identifier_case") and
+           ($value < 1 or $value > 4)) {
+           croak "attribute '$attrib' must have a value from 1 .. 4 
(SQL_IC_UPPER .. SQL_IC_MIXED)";
+           }
+
+        if (( 0 == index( $attrib, "f_" ) and 
$dbh->{f_readonly_attrs}->{$attrib}) or 
+            ( 0 == index( $attrib, "sql_" ) and 
$dbh->{sql_readonly_attrs}->{$attrib}) and
+           defined($dbh->{$attrib})) {
+           croak "attribute '$attrib' is readonly and must not be modified";
+           }
+
        $dbh->{$attrib} = $value;
        return 1;
        }
@@ -403,7 +438,7 @@
            : eval { getpwuid ((stat $dir)[4]) }; # XXX Win32::pwent
        while (defined ($file = readdir ($dirh))) {
            my ($tbl, $meta) = $class->get_table_meta ($dbh, $file, 0, 0) or 
next; # XXX
-           $tbl && $meta && -f $meta->{f_fqfn} or next;
+           # $tbl && $meta && -f $meta->{f_fqfn} or next;
            push @tables, [ undef, $schema, $tbl, "TABLE", undef ];
            }
        unless (closedir $dirh) {
@@ -668,6 +703,9 @@
 use strict;
 use Carp;
 require IO::File;
+require File::Basename;
+require File::Spec;
+require Cwd;
 
 # We may have a working flock () built-in but that doesn't mean that locking
 # will work on NFS (flock () may hang hard)
@@ -683,11 +721,11 @@
 # must not rely on an instantiated DBD::File::Table
 sub file2table
 {
-    my ($self, $meta, $file, $file_is_table, $quoted) = @_;
+    my ($self, $meta, $file, $file_is_table, $respect_case) = @_;
 
-    $file eq "." || $file eq ".."      and return;
+    $file eq "." || $file eq ".."      and return; # XXX would break a 
possible DBD::Dir
 
-    my ($ext, $req) = ("", 0); # XXX
+    my ($ext, $req) = ("", 0);
     if ($meta->{f_ext}) {
        ($ext, my $opt) = split m/\//, $meta->{f_ext};
        if ($ext && $opt) {
@@ -695,20 +733,29 @@
            }
        }
 
-    (my $tbl = $file) =~ s/$ext$//i;
+    # (my $tbl = $file) =~ s/$ext$//i;
+    my ( $tbl, $dir, undef ) = File::Basename::fileparse( $file, $ext );
+    Cwd::abs_path( $dir ) eq $meta->{f_dir} and
+        $dir = "";
+    !$respect_case and $meta->{sql_identifier_case} == 1 and # XXX SQL_IC_UPPER
+        $tbl = uc($tbl);
+    !$respect_case and $meta->{sql_identifier_case} == 2 and # XXX SQL_IC_LOWER
+        $tbl = lc($tbl);
     $file_is_table and $file = "$tbl$ext";
+    my $searchdir = File::Spec->file_name_is_absolute ($dir) ? $dir : 
File::Spec->catdir ($meta->{f_dir}, $dir);
 
     # Fully Qualified File Name
-    unless ($quoted) { # table names are case insensitive in SQL
-       my $dir = $meta->{f_dir};
-       opendir my $dh, $dir or croak "Can't open '$dir': $!";
+    unless ($respect_case) { # table names are case insensitive in SQL
+       opendir my $dh, $searchdir or croak "Can't open '$searchdir': $!";
        my @f = grep { lc $_ eq lc $file } readdir $dh;
-       @f == 1 and $tbl = $file = $f[0];
-       $tbl =~ s/$ext$//i; # XXX /i flag only when not quoted?
-       closedir $dh or croak "Can't close '$dir': $!";
-       }
-    my $fqfn = File::Spec->catfile ($meta->{f_dir}, $file);
-    my $fqbn = File::Spec->catfile ($meta->{f_dir}, $tbl);
+       @f == 1 and $file = $f[0];
+       !$respect_case and $meta->{sql_identifier_case} == 4 and # XXX 
SQL_IC_MIXED
+           ($tbl = $file ) =~ s/$ext$//i;
+       closedir $dh or croak "Can't close '$searchdir': $!";
+       }
+    my $fqfn = Cwd::abs_path( File::Spec->catfile ($searchdir, $file) );
+    my $fqbn = File::Spec->catfile ($searchdir, $tbl);
+    $dir and $tbl = File::Spec->catfile ($dir, $tbl);
 
     $file = $fqfn;
     if ($ext) {
@@ -728,60 +775,61 @@
     !defined ($meta->{f_lockfile}) && $meta->{f_lockfile} and
        $meta->{f_fqln} = $meta->{f_fqbn} . $meta->{f_lockfile};
 
+    $meta->{table_name} = $tbl;
+    $respect_case or $tbl = lc($tbl); # for internal storage
+
     return $tbl;
     } # file2table
 
-my $open_table_re = sprintf "(?:%s|%s|%s)",
-    quotemeta (File::Spec->curdir  ()),
-    quotemeta (File::Spec->updir   ()),
-    quotemeta (File::Spec->rootdir ());
-
-sub init_table_meta ($$$$$)
+sub bootstrap_table_meta ($$$$$)
 {
-    my ($self, $dbh, $table, $file_is_table, $quoted) = @_;
+    my ($self, $dbh, $meta, $table) = @_;
 
-    defined $dbh->{f_meta}{$table} and "HASH" eq ref $dbh->{f_meta}{$table} or
-        $dbh->{f_meta}{$table} = {};
-    my $meta = $dbh->{f_meta}{$table};
     exists  $meta->{f_dir}     or $meta->{f_dir}       = $dbh->{f_dir};
     defined $meta->{f_ext}     or $meta->{f_ext}       = $dbh->{f_ext};
     defined $meta->{f_encoding}        or $meta->{f_encoding}  = 
$dbh->{f_encoding};
     exists  $meta->{f_lock}    or $meta->{f_lock}      = $dbh->{f_lock};
     exists  $meta->{f_lockfile}        or $meta->{f_lockfile}  = 
$dbh->{f_lockfile};
     defined $meta->{f_schema}  or $meta->{f_schema}    = $dbh->{f_schema};
-    unless (defined $meta->{f_fqfn}) {
-       my $tbl = $self->file2table ($meta, $table, $file_is_table, $quoted);
-       $tbl or $meta->{f_fqfn} = undef;
-       }
-    } # init_table_meta
+    defined $meta->{sql_identifier_case} or
+        $meta->{sql_identifier_case} = $dbh->{sql_identifier_case};
+    } # bootstrap_table_meta
 
-sub default_table_meta ($$$)
+sub init_table_meta ($$$$$)
 {
-    my ($self, $dbh, $table) = @_;
-    my $meta = { f_fqfn => $table, f_fqbn => $table };
-    return $meta;
+    my ($self, $dbh, $meta, $table) = @_;
+
+    return;
     } # init_table_meta
 
 sub get_table_meta ($$$$;$)
 {
-    my ($self, $dbh, $table, $file_is_table, $quoted) = @_;
-    unless (defined $quoted) {
-       $quoted = 0;
-       $table =~ s/^\"// and $quoted = 1;    # handle quoted identifiers
+    my ($self, $dbh, $table, $file_is_table, $respect_case) = @_;
+    unless (defined $respect_case) {
+       $respect_case = 0;
+       $table =~ s/^\"// and $respect_case = 1;    # handle quoted identifiers
        $table =~ s/\"$//;
        }
 
     my $meta;
-    if (    $table !~ m/^$open_table_re/o
-       and $table !~ m{^[/\\]}      # root
-       and $table !~ m{^[a-z]\:}    # drive letter
-       ) {
-       # should be done anyway, table_info might generate incomplete f_meta
-       $self->init_table_meta ($dbh, $table, $file_is_table, $quoted);
+    if( defined( $dbh->{f_meta}->{$table} ) ) {
        $meta = $dbh->{f_meta}->{$table};
        }
     else {
-       $meta = $self->default_table_meta ($dbh, $table);
+       $meta = {};
+       }
+
+    unless( $meta->{initialized} ) {
+       $self->bootstrap_table_meta($dbh, $meta, $table);
+
+       unless (defined $meta->{f_fqfn}) {
+           $table = $self->file2table ($meta, $table, $file_is_table, 
$respect_case);
+           $table or return;
+           }
+
+       $self->init_table_meta ($dbh, $meta, $table);
+       $meta->{initialized} = 1;
+       $dbh->{f_meta}->{$table} = $meta;
        }
 
     return ($table, $meta);

Modified: dbi/trunk/t/49dbd_file.t
==============================================================================
--- dbi/trunk/t/49dbd_file.t    (original)
+++ dbi/trunk/t/49dbd_file.t    Fri May 28 10:53:32 2010
@@ -59,7 +59,7 @@
        local $SIG{__DIE__} = sub { push @msg, @_ };
        $sth->execute;
        };
-    like ("@msg", qr{Cannot open ./t_sbdgf_}, "Cannot open non-existing file");
+    like ("@msg", qr{Cannot open .*/t_sbdgf_}, "Cannot open non-existing 
file");
     }
 
 my @tfhl;

Reply via email to