diff --git a/bin/pt-query-digest b/bin/pt-query-digest index 29e0d785..03365a36 100755 --- a/bin/pt-query-digest +++ b/bin/pt-query-digest @@ -492,12 +492,18 @@ sub quote_val { sub split_unquote { my ( $self, $db_tbl, $default_db ) = @_; - $db_tbl =~ s/`//g; my ( $db, $tbl ) = split(/[.]/, $db_tbl); if ( !$tbl ) { $tbl = $db; $db = $default_db; } + for ($db, $tbl) { + next unless $_; + s/\A`//; + s/`\z//; + s/``/`/g; + } + return ($db, $tbl); } @@ -6715,7 +6721,7 @@ sub event_report { } my $line = sprintf( - '# %s %d: %s QPS, %sx concurrency, ID 0x%s at byte %d ', + '# %s %d: %s QPS, %sx concurrency, ID 0x%s at byte %.f ', ($ea->{groupby} eq 'fingerprint' ? 'Query' : 'Item'), $args{rank} || 0, shorten($qps || 0, d=>1_000), @@ -8103,16 +8109,20 @@ $Data::Dumper::Indent = 1; $Data::Dumper::Sortkeys = 1; $Data::Dumper::Quotekeys = 0; +local $EVAL_ERROR; +eval { + require Quoter; +}; + sub new { my ( $class, %args ) = @_; - my @required_args = qw(Quoter); - foreach my $arg ( @required_args ) { - die "I need a $arg argument" unless $args{$arg}; - } my $self = { %args }; + $self->{Quoter} ||= Quoter->new(); return bless $self, $class; } +sub Quoter { shift->{Quoter} } + sub get_create_table { my ( $self, $dbh, $db, $tbl ) = @_; die "I need a dbh parameter" unless $dbh; diff --git a/lib/QueryReportFormatter.pm b/lib/QueryReportFormatter.pm index f1865937..95eff7c2 100644 --- a/lib/QueryReportFormatter.pm +++ b/lib/QueryReportFormatter.pm @@ -524,7 +524,7 @@ sub event_report { # First line like: # Query 1: 9 QPS, 0x concurrency, ID 0x7F7D57ACDD8A346E at byte 5 ________ my $line = sprintf( - '# %s %d: %s QPS, %sx concurrency, ID 0x%s at byte %d ', + '# %s %d: %s QPS, %sx concurrency, ID 0x%s at byte %.f ', ($ea->{groupby} eq 'fingerprint' ? 'Query' : 'Item'), $args{rank} || 0, shorten($qps || 0, d=>1_000), diff --git a/t/lib/QueryReportFormatter.t b/t/lib/QueryReportFormatter.t index 1124cab0..68c214f5 100644 --- a/t/lib/QueryReportFormatter.t +++ b/t/lib/QueryReportFormatter.t @@ -9,7 +9,7 @@ BEGIN { use strict; use warnings FATAL => 'all'; use English qw(-no_match_vars); -use Test::More tests => 45; +use Test::More; use Data::Dumper; $Data::Dumper::Indent = 1; @@ -187,6 +187,38 @@ ok( 'Event report' ); +{ + # pt-query-digest prints negative byte offset + # https://bugs.launchpad.net/percona-toolkit/+bug/887638 + + # printf "%d" can't really handle large values in some systems. + # Given a large enough log file, it will start printing + # negative values. The workaround is to use %.f instead. I haven't + # researched what the recommended solution for this is, but + # it's such an uncommon case and that it's not worth the time. + # This bug should really only affect 32-bit machines, and even then + # only those were the underlaying compiler's printf("%d") coerces the + # argument into a signed int. + my $item = 'select id from users where name=?'; + local $ea->results->{samples}->{$item}->{pos_in_log} = 1e+33; + + $result = $qrf->event_report( + ea => $ea, + # "users" is here to try to cause a failure + select => [ qw(Query_time Lock_time Rows_sent Rows_examined ts db user users) ], + item => $item, + rank => 1, + orderby => 'Query_time', + reason => 'top', + ); + + unlike( + $result, + qr/at byte -/, + "Bug 887638: pt-query-digest prints negative byte offset" + ); +} + $result = $qrf->chart_distro( ea => $ea, attrib => 'Query_time', @@ -1570,4 +1602,5 @@ like( '_d() works' ); ok($sb->ok(), "Sandbox servers") or BAIL_OUT(__FILE__ . " broke the sandbox"); +done_testing; exit;