Author: timbo
Date: Tue Nov 29 11:51:00 2005
New Revision: 2286
Modified:
dbi/trunk/Changes
dbi/trunk/MANIFEST
dbi/trunk/META.yml
dbi/trunk/Makefile.PL
dbi/trunk/lib/DBI/ProfileData.pm
dbi/trunk/t/42prof_data.t
Log:
Fixed warning options for gcc
Added Filter mechanism to DBI::ProfileData
Modified: dbi/trunk/Changes
==============================================================================
--- dbi/trunk/Changes (original)
+++ dbi/trunk/Changes Tue Nov 29 11:51:00 2005
@@ -27,6 +27,10 @@ DBI::Changes - List of significant chang
Changed "use DBI" to only set $DBI::connect_via if not already set.
Changed docs to clarify pre-method clearing of err values.
+ Added ability for DBI::ProfileData to edit profile path on loading.
+ This enables aggregation of different SQL statements into the same
+ profile node - very handy when not using placeholders or when working
+ multiple separate tables for the same thing (ie logtable_2005_11_28)
Added $sth->{ParamTypes} specification thanks to Dean Arnold.
Added $h->{Callbacks} attribute to enable code hooks to be invoked
when certain methods are called. For example:
Modified: dbi/trunk/MANIFEST
==============================================================================
--- dbi/trunk/MANIFEST (original)
+++ dbi/trunk/MANIFEST Tue Nov 29 11:51:00 2005
@@ -59,6 +59,7 @@ t/30subclass.t
t/40profile.t
t/41prof_dump.t
t/42prof_data.t
+t/43profenv.t
t/50dbm.t
t/60preparse.t
t/70callbacks.t
Modified: dbi/trunk/META.yml
==============================================================================
--- dbi/trunk/META.yml (original)
+++ dbi/trunk/META.yml Tue Nov 29 11:51:00 2005
@@ -1,10 +1,11 @@
# http://module-build.sourceforge.net/META-spec.html
#XXXXXXX This is a prototype!!! It will change in the future!!! XXXXX#
name: DBI
-version: 1.48
+version: 1.49
version_from: DBI.pm
installdirs: site
requires:
+ Storable: 1
Test::Simple: 0.4
distribution_type: module
Modified: dbi/trunk/Makefile.PL
==============================================================================
--- dbi/trunk/Makefile.PL (original)
+++ dbi/trunk/Makefile.PL Tue Nov 29 11:51:00 2005
@@ -141,13 +141,15 @@ $opts{CAPI} = 'TRUE' if $Config{archname
if (my $gccversion = $Config{gccversion}) { # ask gcc to be more pedantic
warn "WARNING: Your GNU C $gccversion compiler is very old. Please upgrade
it and rebuild perl.\n"
- if $gccversion =~ m/^(1|2\.[1-8])/;
- $opts{CCFLAGS} .= ' -W -Wall -Wpointer-arith -Wmissing-noreturn
-Wbad-function-cast';
+ if $gccversion =~ m/^\D*(1|2\.[1-8])/;
+ $gccversion =~ s/[^\d\.]//g; # just a number please
+ $opts{CCFLAGS} .= ' -W -Wall -Wpointer-arith -Wbad-function-cast';
$opts{CCFLAGS} .= ' -Wno-comment -Wno-sign-compare -Wno-cast-qual';
- $opts{CCFLAGS} .= ' -Wdisabled-optimization' if $gccversion ge "3.0";
- if (0 && $is_developer && $::opt_g) {
+ $opts{CCFLAGS} .= ' -Wdisabled-optimization -Wmissing-noreturn
-Wno-unused-parameter'
+ if $gccversion ge "3.0";
+ if ($is_developer && $::opt_g) {
$opts{CCFLAGS} .= ' -DPERL_GCC_PEDANTIC -ansi -pedantic' if
$gccversion ge "3.0";
- $opts{CCFLAGS} .= ' -Wmissing-prototypes'; # noisy due to XS_* funcs
+ $opts{CCFLAGS} .= ' -Wmissing-prototypes';
}
}
@@ -296,13 +298,13 @@ config :: $(changes_pm) $(roadmap_pm)
$(NOECHO) $(NOOP)
$(changes_pm): Changes
- $(NOECHO) $(MKPATH) $(inst_libdbi)
- $(NOECHO) $(RM_F) $(changes_pm)
+ $(MKPATH) $(inst_libdbi)
+ $(RM_F) $(changes_pm)
$(CP) Changes $(changes_pm)
$(roadmap_pm): Roadmap.pod
- $(NOECHO) $(MKPATH) $(inst_libdbi)
- $(NOECHO) $(RM_F) $(roadmap_pm)
+ $(MKPATH) $(inst_libdbi)
+ $(RM_F) $(roadmap_pm)
$(CP) Roadmap.pod $(roadmap_pm)
';
Modified: dbi/trunk/lib/DBI/ProfileData.pm
==============================================================================
--- dbi/trunk/lib/DBI/ProfileData.pm (original)
+++ dbi/trunk/lib/DBI/ProfileData.pm Tue Nov 29 11:51:00 2005
@@ -91,6 +91,8 @@ sub PATH () { 7 };
=item $prof = DBI::ProfileData->new(File => "dbi.prof")
+=item $prof = DBI::ProfileData->new(File => "dbi.prof", Filter => sub { ... })
+
=item $prof = DBI::ProfileData->new(Files => [ "dbi.prof.1", "dbi.prof.2" ])
Creates a a new DBI::ProfileData object. Takes either a single file
@@ -98,12 +100,43 @@ through the File option or a list of Fil
multiple files are specified then the header data from the first file
is used.
+The C<Filter> parameter can be used to supply a code reference that can
+manipulate the profile data as it is being read. This is most useful for
+editing SQL statements so that slightly different statements in the raw data
+will be merged and aggregated in the loaded data. For example:
+
+ Filter => sub {
+ my ($path_ref, $data_ref) = @_;
+ s/foo = '.*?'/foo = '...'/ for @$path_ref;
+ }
+
+Here's an example that performs some normalization on the SQL. It converts all
+numbers to C<N> and all quoted strings to C<S>. It can also convert digits to
+N within names. Finally, it summarizes long "IN (...)" clauses.
+
+It's aggressive and simplistic, but it's often sufficient, and serves as an
+example that you can tailor to suit your own needs:
+
+ Filter => sub {
+ my ($path_ref, $data_ref) = @_;
+ local $_ = $path_ref->[0]; # whichever element contains the SQL Statement
+ s/\b\d+\b/N/g; # 42 -> N
+ s/\b0x[0-9A-Fa-f]+\b/N/g; # 0xFE -> N
+ s/'.*?'/'S'/g; # single quoted strings (doesn't handle
escapes)
+ s/".*?"/"S"/g; # double quoted strings (doesn't handle
escapes)
+ # convert names like log_20001231 into log_NNNNNNNN, controlled by
$opt{n}
+ s/([a-z_]+)(\d{$opt{n},})/$1.('N' x length($2))/ieg if $opt{n};
+ # abbreviate massive "in (...)" statements and similar
+ s!(([NS],){100,})!sprintf("$2,{repeated %d times}",length($1)/2)!eg;
+ }
+
=cut
sub new {
my $pkg = shift;
my $self = {
Files => [ "dbi.prof" ],
+ Filter => undef,
_header => {},
_nodes => [],
_node_lookup => {},
@@ -164,6 +197,7 @@ sub _read_body {
my ($self, $fh, $filename) = @_;
my $nodes = $self->{_nodes};
my $lookup = $self->{_node_lookup};
+ my $filter = $self->{Filter};
# build up node array
my @path = ("");
@@ -197,6 +231,11 @@ sub _read_body {
# no data?
croak("Invalid data syntax format in $filename line $.: $_")
unless @data;
+ # hook to enable pre-processing of the data - such as mangling SQL
+ # so that slightly different statements get treated as the same
+ # and so merged in the results
+ $filter->([EMAIL PROTECTED], [EMAIL PROTECTED]) if $filter;
+
# elements of @path can't have NULLs in them, so this
# forms a unique string per @path. If there's some way I
# can get this without arbitrarily stripping out a
Modified: dbi/trunk/t/42prof_data.t
==============================================================================
--- dbi/trunk/t/42prof_data.t (original)
+++ dbi/trunk/t/42prof_data.t Tue Nov 29 11:51:00 2005
@@ -11,7 +11,7 @@ BEGIN {
plan skip_all => 'profiling not supported for DBI::PurePerl';
}
else {
- plan tests => 32;
+ plan tests => 33;
}
}
@@ -28,6 +28,7 @@ isa_ok( $dbh, 'DBI::db', 'Created connec
# do a little work
foreach (1,2,3) {
+ $dbh->do("set dummy=$_");
my $sth = $dbh->prepare($sql);
isa_ok( $sth, 'DBI::st', 'Created handle' );
for my $loop (1..20) {
@@ -45,7 +46,10 @@ undef $dbh;
ok(-s "dbi.prof", "Profile written to disk, non-zero size" );
# load up
-my $prof = DBI::ProfileData->new();
+my $prof = DBI::ProfileData->new( Filter => sub {
+ my ($path_ref, $data_ref) = @_;
+ $path_ref->[0] =~ s/set dummy=\d/set dummy=N/;
+});
isa_ok( $prof, 'DBI::ProfileData' );
cmp_ok( $prof->count, '>=', 3, 'At least 3 profile data items' );
@@ -83,9 +87,13 @@ ok($clone->count == 1);
# take a look through Data
my $Data = $prof->Data;
+print "SQL: $_\n" for keys %$Data;
ok(exists($Data->{$sql}));
ok(exists($Data->{$sql}{execute}));
+# did the Filter convert set dummy=1 (etc) into set dummy=N?
+ok(exists($Data->{"set dummy=N"}));
+
# test escaping of \n and \r in keys
$dbh = DBI->connect("dbi:ExampleP:", '', '',
{ RaiseError=>1, Profile=>"6/DBI::ProfileDumper" });