Apache-LoggedAuthDBI
view release on metacpan or search on metacpan
printf " %-16s: %s\n",$_,$version{$_}
for reverse sort keys %version;
}
return \%version;
}
sub data_sources {
my ($class, $driver, @other) = @_;
my $drh = $class->install_driver($driver);
my @ds = $drh->data_sources(@other);
return @ds;
}
sub neat_list {
my ($listref, $maxlen, $sep) = @_;
$maxlen = 0 unless defined $maxlen; # 0 == use internal default
$sep = ", " unless defined $sep;
join($sep, map { neat($_,$maxlen) } @$listref);
}
sub dump_results { # also aliased as a method in DBD::_::st
my ($sth, $maxlen, $lsep, $fsep, $fh) = @_;
return 0 unless $sth;
$maxlen ||= 35;
$lsep ||= "\n";
$fh ||= \*STDOUT;
my $rows = 0;
my $ref;
while($ref = $sth->fetch) {
print $fh $lsep if $rows++ and $lsep;
my $str = neat_list($ref,$maxlen,$fsep);
print $fh $str; # done on two lines to avoid 5.003 errors
}
print $fh "\n$rows rows".($DBI::err ? " ($DBI::err: $DBI::errstr)" : "")."\n";
$rows;
}
sub data_diff {
my ($a, $b, $logical) = @_;
my $diff = data_string_diff($a, $b);
return "" if $logical and !$diff;
my $a_desc = data_string_desc($a);
my $b_desc = data_string_desc($b);
return "" if !$diff and $a_desc eq $b_desc;
$diff ||= "Strings contain the same sequence of characters"
if length($a);
$diff .= "\n" if $diff;
return "a: $a_desc\nb: $b_desc\n$diff";
}
sub data_string_diff {
# Compares 'logical' characters, not bytes, so a latin1 string and an
# an equivalent unicode string will compare as equal even though their
# byte encodings are different.
my ($a, $b) = @_;
unless (defined $a and defined $b) { # one undef
return ""
if !defined $a and !defined $b;
return "String a is undef, string b has ".length($b)." characters"
if !defined $a;
return "String b is undef, string a has ".length($a)." characters"
if !defined $b;
}
require utf8;
# hack to cater for perl 5.6
*utf8::is_utf8 = sub { (DBI::neat(shift)=~/^"/) } unless defined &utf8::is_utf8;
my @a_chars = (utf8::is_utf8($a)) ? unpack("U*", $a) : unpack("C*", $a);
my @b_chars = (utf8::is_utf8($b)) ? unpack("U*", $b) : unpack("C*", $b);
my $i = 0;
while (@a_chars && @b_chars) {
++$i, shift(@a_chars), shift(@b_chars), next
if $a_chars[0] == $b_chars[0];# compare ordinal values
my @desc = map {
$_ > 255 ? # if wide character...
sprintf("\\x{%04X}", $_) : # \x{...}
chr($_) =~ /[[:cntrl:]]/ ? # else if control character ...
sprintf("\\x%02X", $_) : # \x..
chr($_) # else as themselves
} ($a_chars[0], $b_chars[0]);
# highlight probable double-encoding?
foreach my $c ( @desc ) {
next unless $c =~ m/\\x\{08(..)}/;
$c .= "='" .chr(hex($1)) ."'"
}
return sprintf "Strings differ at index $i: a[$i]=$desc[0], b[$i]=$desc[1]";
}
return "String a truncated after $i characters" if @b_chars;
return "String b truncated after $i characters" if @a_chars;
return "";
}
sub data_string_desc { # describe a data string
my ($a) = @_;
require bytes;
require utf8;
# hacks to cater for perl 5.6
*utf8::is_utf8 = sub { (DBI::neat(shift)=~/^"/) } unless defined &utf8::is_utf8;
*utf8::valid = sub { 1 } unless defined &utf8::valid;
# Give sufficient info to help diagnose at least these kinds of situations:
# - valid UTF8 byte sequence but UTF8 flag not set
# (might be ascii so also need to check for hibit to make it worthwhile)
# - UTF8 flag set but invalid UTF8 byte sequence
# could do better here, but this'll do for now
my $utf8 = sprintf "UTF8 %s%s",
utf8::is_utf8($a) ? "on" : "off",
utf8::valid($a||'') ? "" : " but INVALID encoding";
return "$utf8, undef" unless defined $a;
my $is_ascii = $a =~ m/^[\000-\177]*$/;
( run in 0.628 second using v1.01-cache-2.11-cpan-cdf2f3d4e48 )