mirror of
https://github.com/percona/percona-toolkit.git
synced 2025-09-10 21:19:59 +00:00
Merge 2.1.8 and 2.2.
This commit is contained in:
36
Changelog
36
Changelog
@@ -1,5 +1,41 @@
|
||||
Changelog for Percona Toolkit
|
||||
|
||||
v2.1.8 released 2012-12-21
|
||||
|
||||
* Beta support for MySQL 5.6
|
||||
* Beta support for Percona XtraDB Cluster
|
||||
* pt-online-schema-change: If ran on Percona XtraDB Cluster, requires PXC 5.5.28 or newer
|
||||
* pt-table-checksum: If ran on Percona XtraDB Cluster, requires PXC 5.5.28 or newer
|
||||
* pt-upgrade: Added --[no]disable-query-cache
|
||||
* Fixed bug 927955: Bad pod2rst transformation
|
||||
* Fixed bug 898665: Bad online docs formatting for --[no]vars
|
||||
* Fixed bug 1022622: pt-config-diff is case-sensitive
|
||||
* Fixed bug 1007938: pt-config-diff doesn't handle end-of-line comments
|
||||
* Fixed bug 917770: pt-config-diff Use of uninitialized value in substitution (s///) at line 1996
|
||||
* Fixed bug 1082104: pt-deadlock-logger doesn't handle usernames with dashes
|
||||
* Fixed bug 886059: pt-heartbeat handles timezones inconsistently
|
||||
* Fixed bug 1086259: pt-kill --log-dsn timestamp is wrong
|
||||
* Fixed bug 1015590: pt-mysql-summary doesn't handle renamed variables in Percona Server 5.5
|
||||
* Fixed bug 1079341: pt-online-schema-change checks for foreign keys on MyISAM tables
|
||||
* Fixed bug 823431: pt-query-advisor hangs on big queries
|
||||
* Fixed bug 996069: pt-query-advisor RES.001 is incorrect
|
||||
* Fixed bug 933465: pt-query-advisor false positive on RES.001
|
||||
* Fixed bug 937234: pt-query-advisor issues wrong RES.001
|
||||
* Fixed bug 1082599: pt-query-digest fails to parse timestamp with no query
|
||||
* Fixed bug 1078838: pt-query-digest doesn't parse general log with "Connect user as user"
|
||||
* Fixed bug 957442: pt-query-digest with custom --group-by throws error
|
||||
* Fixed bug 887638: pt-query-digest prints negative byte offset
|
||||
* Fixed bug 831525: pt-query-digest help output mangled
|
||||
* Fixed bug 932614: pt-slave-restart CHANGE MASTER query causes error
|
||||
* Fixed bug 1046440: pt-stalk purge_samples slows down checks
|
||||
* Fixed bug 986847: pt-stalk does not report NFS iostat
|
||||
* Fixed bug 1074179: pt-table-checksum doesn't ignore tables for --replicate-check-only
|
||||
* Fixed bug 911385: pt-table-checksum v2 fails when --resume + --ignore-database is used
|
||||
* Fixed bug 1041391: pt-table-checksum debug statement for "Chosen hash func" prints undef
|
||||
* Fixed bug 1075638: pt-table-checksum Illegal division by zero at line 7950
|
||||
* Fixed bug 1052475: pt-table-checksum uninitialized value in numeric lt (<) at line 8611
|
||||
* Fixed bug 1078887: Tools let --set-vars clobber the required SQL mode
|
||||
|
||||
v2.1.7 released 2012-11-19
|
||||
|
||||
* Fixed bug 1080384: pt-table-checksum 2.1.6 crashes using PTDEBUG
|
||||
|
@@ -2,7 +2,7 @@ use ExtUtils::MakeMaker;
|
||||
|
||||
WriteMakefile(
|
||||
NAME => 'percona-toolkit',
|
||||
VERSION => '2.1.7',
|
||||
VERSION => '2.1.8',
|
||||
EXE_FILES => [ <bin/*> ],
|
||||
MAN1PODS => {
|
||||
'docs/percona-toolkit.pod' => 'blib/man1/percona-toolkit.1p',
|
||||
|
@@ -199,8 +199,8 @@ L<http://www.percona.com/software/> for more software developed by Percona.
|
||||
|
||||
=head1 COPYRIGHT, LICENSE, AND WARRANTY
|
||||
|
||||
This program is copyright 2010-2011 Baron Schwartz, 2011-2012 Percona Inc.
|
||||
Feedback and improvements are welcome.
|
||||
This program is copyright 2011-2013 Percona Ireland Ltd,
|
||||
2010-2011 Baron Schwartz.
|
||||
|
||||
THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
@@ -218,6 +218,6 @@ Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
pt-align 2.1.7
|
||||
pt-align 2.1.8
|
||||
|
||||
=cut
|
||||
|
@@ -39,7 +39,7 @@ BEGIN {
|
||||
# ###########################################################################
|
||||
{
|
||||
package Percona::Toolkit;
|
||||
our $VERSION = '2.1.7';
|
||||
our $VERSION = '2.1.8';
|
||||
|
||||
1;
|
||||
}
|
||||
@@ -7555,8 +7555,8 @@ L<http://www.percona.com/software/> for more software developed by Percona.
|
||||
|
||||
=head1 COPYRIGHT, LICENSE, AND WARRANTY
|
||||
|
||||
This program is copyright 2007-2011 Baron Schwartz, 2011-2012 Percona Inc.
|
||||
Feedback and improvements are welcome.
|
||||
This program is copyright 2011-2013 Percona Ireland Ltd,
|
||||
2007-2011 Baron Schwartz.
|
||||
|
||||
THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
@@ -7574,6 +7574,6 @@ Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
pt-archiver 2.1.7
|
||||
pt-archiver 2.1.8
|
||||
|
||||
=cut
|
||||
|
@@ -14,6 +14,7 @@ use warnings FATAL => 'all';
|
||||
BEGIN {
|
||||
$INC{$_} = __FILE__ for map { (my $pkg = "$_.pm") =~ s!::!/!g; $pkg } (qw(
|
||||
Percona::Toolkit
|
||||
Mo
|
||||
OptionParser
|
||||
DSNParser
|
||||
Cxn
|
||||
@@ -38,7 +39,7 @@ BEGIN {
|
||||
# ###########################################################################
|
||||
{
|
||||
package Percona::Toolkit;
|
||||
our $VERSION = '2.1.7';
|
||||
our $VERSION = '2.1.8';
|
||||
|
||||
1;
|
||||
}
|
||||
@@ -46,6 +47,470 @@ our $VERSION = '2.1.7';
|
||||
# End Percona::Toolkit package
|
||||
# ###########################################################################
|
||||
|
||||
# ###########################################################################
|
||||
# Mo package
|
||||
# This package is a copy without comments from the original. The original
|
||||
# with comments and its test file can be found in the Bazaar repository at,
|
||||
# lib/Mo.pm
|
||||
# t/lib/Mo.t
|
||||
# See https://launchpad.net/percona-toolkit for more information.
|
||||
# ###########################################################################
|
||||
{
|
||||
BEGIN {
|
||||
$INC{"Mo.pm"} = __FILE__;
|
||||
package Mo;
|
||||
our $VERSION = '0.30_Percona'; # Forked from 0.30 of Mo.
|
||||
|
||||
{
|
||||
no strict 'refs';
|
||||
sub _glob_for {
|
||||
return \*{shift()}
|
||||
}
|
||||
|
||||
sub _stash_for {
|
||||
return \%{ shift() . "::" };
|
||||
}
|
||||
}
|
||||
|
||||
use strict;
|
||||
use warnings qw( FATAL all );
|
||||
|
||||
use Carp ();
|
||||
use Scalar::Util qw(looks_like_number blessed);
|
||||
|
||||
|
||||
our %TYPES = (
|
||||
Bool => sub { !$_[0] || (defined $_[0] && looks_like_number($_[0]) && $_[0] == 1) },
|
||||
Num => sub { defined $_[0] && looks_like_number($_[0]) },
|
||||
Int => sub { defined $_[0] && looks_like_number($_[0]) && $_[0] == int($_[0]) },
|
||||
Str => sub { defined $_[0] },
|
||||
Object => sub { defined $_[0] && blessed($_[0]) },
|
||||
FileHandle => sub { local $@; require IO::Handle; fileno($_[0]) && $_[0]->opened },
|
||||
|
||||
map {
|
||||
my $type = /R/ ? $_ : uc $_;
|
||||
$_ . "Ref" => sub { ref $_[0] eq $type }
|
||||
} qw(Array Code Hash Regexp Glob Scalar)
|
||||
);
|
||||
|
||||
our %metadata_for;
|
||||
{
|
||||
package Mo::Object;
|
||||
|
||||
sub new {
|
||||
my $class = shift;
|
||||
my $args = $class->BUILDARGS(@_);
|
||||
|
||||
my @args_to_delete;
|
||||
while ( my ($attr, $meta) = each %{$metadata_for{$class}} ) {
|
||||
next unless exists $meta->{init_arg};
|
||||
my $init_arg = $meta->{init_arg};
|
||||
|
||||
if ( defined $init_arg ) {
|
||||
$args->{$attr} = delete $args->{$init_arg};
|
||||
}
|
||||
else {
|
||||
push @args_to_delete, $attr;
|
||||
}
|
||||
}
|
||||
|
||||
delete $args->{$_} for @args_to_delete;
|
||||
|
||||
for my $attribute ( keys %$args ) {
|
||||
if ( my $coerce = $metadata_for{$class}{$attribute}{coerce} ) {
|
||||
$args->{$attribute} = $coerce->($args->{$attribute});
|
||||
}
|
||||
if ( my $I = $metadata_for{$class}{$attribute}{isa} ) {
|
||||
( (my $I_name), $I ) = @{$I};
|
||||
Mo::_check_type_constaints($attribute, $I, $I_name, $args->{$attribute});
|
||||
}
|
||||
}
|
||||
|
||||
while ( my ($attribute, $meta) = each %{$metadata_for{$class}} ) {
|
||||
next unless $meta->{required};
|
||||
Carp::confess("Attribute ($attribute) is required for $class")
|
||||
if ! exists $args->{$attribute}
|
||||
}
|
||||
|
||||
@_ = %$args;
|
||||
my $self = bless $args, $class;
|
||||
|
||||
my @build_subs;
|
||||
my $linearized_isa = mro::get_linear_isa($class);
|
||||
|
||||
for my $isa_class ( @$linearized_isa ) {
|
||||
unshift @build_subs, *{ Mo::_glob_for "${isa_class}::BUILD" }{CODE};
|
||||
}
|
||||
exists &$_ && $_->( $self, @_ ) for grep { defined } @build_subs;
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub BUILDARGS {
|
||||
shift;
|
||||
my $ref;
|
||||
if ( @_ == 1 && ref($_[0]) ) {
|
||||
Carp::confess("Single parameters to new() must be a HASH ref")
|
||||
unless ref($_[0]) eq ref({});
|
||||
$ref = {%{$_[0]}} # We want a new reference, always
|
||||
}
|
||||
else {
|
||||
$ref = { @_ };
|
||||
}
|
||||
return $ref;
|
||||
}
|
||||
}
|
||||
|
||||
my %export_for;
|
||||
%Mo::Internal::Keyword = map { $_ => 1 } qw(has extends override);
|
||||
|
||||
sub Mo::import {
|
||||
warnings->import(qw(FATAL all));
|
||||
strict->import();
|
||||
|
||||
my $caller = scalar caller(); # Caller's package
|
||||
my $caller_pkg = $caller . "::"; # Caller's package with :: at the end
|
||||
my (%exports, %options);
|
||||
|
||||
my (undef, @features) = @_;
|
||||
my %ignore = ( map { $_ => 1 } qw( is isa init_arg builder buildargs clearer predicate build handles default required ) );
|
||||
for my $feature (grep { !$ignore{$_} } @features) {
|
||||
{ local $@; require "Mo/$feature.pm"; }
|
||||
{
|
||||
no strict 'refs';
|
||||
&{"Mo::${feature}::e"}(
|
||||
$caller_pkg,
|
||||
\%exports,
|
||||
\%options,
|
||||
\@_
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return if $exports{M};
|
||||
|
||||
%exports = (
|
||||
extends => sub {
|
||||
for my $class ( map { "$_" } @_ ) {
|
||||
$class =~ s{::|'}{/}g;
|
||||
{ local $@; eval { require "$class.pm" } } # or warn $@;
|
||||
}
|
||||
_set_package_isa($caller, @_);
|
||||
_set_inherited_metadata($caller);
|
||||
},
|
||||
override => \&override,
|
||||
has => sub {
|
||||
my $names = shift;
|
||||
for my $attribute ( ref $names ? @$names : $names ) {
|
||||
my %args = @_;
|
||||
my $method = ($args{is} || '') eq 'ro'
|
||||
? sub {
|
||||
Carp::confess("Cannot assign a value to a read-only accessor at reader ${caller_pkg}${attribute}")
|
||||
if $#_;
|
||||
return $_[0]{$attribute};
|
||||
}
|
||||
: sub {
|
||||
return $#_
|
||||
? $_[0]{$attribute} = $_[1]
|
||||
: $_[0]{$attribute};
|
||||
};
|
||||
|
||||
$metadata_for{$caller}{$attribute} = ();
|
||||
|
||||
if ( my $I = $args{isa} ) {
|
||||
my $orig_I = $I;
|
||||
my $type;
|
||||
if ( $I =~ /\A(ArrayRef|Maybe)\[(.*)\]\z/ ) {
|
||||
$I = _nested_constraints($attribute, $1, $2);
|
||||
}
|
||||
$metadata_for{$caller}{$attribute}{isa} = [$orig_I, $I];
|
||||
my $orig_method = $method;
|
||||
$method = sub {
|
||||
if ( $#_ ) {
|
||||
Mo::_check_type_constaints($attribute, $I, $orig_I, $_[1]);
|
||||
}
|
||||
goto &$orig_method;
|
||||
};
|
||||
}
|
||||
|
||||
if ( my $builder = $args{builder} ) {
|
||||
my $original_method = $method;
|
||||
$method = sub {
|
||||
$#_
|
||||
? goto &$original_method
|
||||
: ! exists $_[0]{$attribute}
|
||||
? $_[0]{$attribute} = $_[0]->$builder
|
||||
: goto &$original_method
|
||||
};
|
||||
}
|
||||
|
||||
if ( my $code = $args{default} ) {
|
||||
Carp::confess("${caller}::${attribute}'s default is $code, but should be a coderef")
|
||||
unless ref($code) eq 'CODE';
|
||||
my $original_method = $method;
|
||||
$method = sub {
|
||||
$#_
|
||||
? goto &$original_method
|
||||
: ! exists $_[0]{$attribute}
|
||||
? $_[0]{$attribute} = $_[0]->$code
|
||||
: goto &$original_method
|
||||
};
|
||||
}
|
||||
|
||||
if ( my $role = $args{does} ) {
|
||||
my $original_method = $method;
|
||||
$method = sub {
|
||||
if ( $#_ ) {
|
||||
Carp::confess(qq<Attribute ($attribute) doesn't consume a '$role' role">)
|
||||
unless Scalar::Util::blessed($_[1]) && eval { $_[1]->does($role) }
|
||||
}
|
||||
goto &$original_method
|
||||
};
|
||||
}
|
||||
|
||||
if ( my $coercion = $args{coerce} ) {
|
||||
$metadata_for{$caller}{$attribute}{coerce} = $coercion;
|
||||
my $original_method = $method;
|
||||
$method = sub {
|
||||
if ( $#_ ) {
|
||||
return $original_method->($_[0], $coercion->($_[1]))
|
||||
}
|
||||
goto &$original_method;
|
||||
}
|
||||
}
|
||||
|
||||
$method = $options{$_}->($method, $attribute, @_)
|
||||
for sort keys %options;
|
||||
|
||||
*{ _glob_for "${caller}::$attribute" } = $method;
|
||||
|
||||
if ( $args{required} ) {
|
||||
$metadata_for{$caller}{$attribute}{required} = 1;
|
||||
}
|
||||
|
||||
if ($args{clearer}) {
|
||||
*{ _glob_for "${caller}::$args{clearer}" }
|
||||
= sub { delete shift->{$attribute} }
|
||||
}
|
||||
|
||||
if ($args{predicate}) {
|
||||
*{ _glob_for "${caller}::$args{predicate}" }
|
||||
= sub { exists shift->{$attribute} }
|
||||
}
|
||||
|
||||
if ($args{handles}) {
|
||||
_has_handles($caller, $attribute, \%args);
|
||||
}
|
||||
|
||||
if (exists $args{init_arg}) {
|
||||
$metadata_for{$caller}{$attribute}{init_arg} = $args{init_arg};
|
||||
}
|
||||
}
|
||||
},
|
||||
%exports,
|
||||
);
|
||||
|
||||
$export_for{$caller} = [ keys %exports ];
|
||||
|
||||
for my $keyword ( keys %exports ) {
|
||||
*{ _glob_for "${caller}::$keyword" } = $exports{$keyword}
|
||||
}
|
||||
*{ _glob_for "${caller}::extends" }{CODE}->( "Mo::Object" )
|
||||
unless @{ *{ _glob_for "${caller}::ISA" }{ARRAY} || [] };
|
||||
};
|
||||
|
||||
sub _check_type_constaints {
|
||||
my ($attribute, $I, $I_name, $val) = @_;
|
||||
( ref($I) eq 'CODE'
|
||||
? $I->($val)
|
||||
: (ref $val eq $I
|
||||
|| ($val && $val eq $I)
|
||||
|| (exists $TYPES{$I} && $TYPES{$I}->($val)))
|
||||
)
|
||||
|| Carp::confess(
|
||||
qq<Attribute ($attribute) does not pass the type constraint because: >
|
||||
. qq<Validation failed for '$I_name' with value >
|
||||
. (defined $val ? Mo::Dumper($val) : 'undef') )
|
||||
}
|
||||
|
||||
sub _has_handles {
|
||||
my ($caller, $attribute, $args) = @_;
|
||||
my $handles = $args->{handles};
|
||||
|
||||
my $ref = ref $handles;
|
||||
my $kv;
|
||||
if ( $ref eq ref [] ) {
|
||||
$kv = { map { $_,$_ } @{$handles} };
|
||||
}
|
||||
elsif ( $ref eq ref {} ) {
|
||||
$kv = $handles;
|
||||
}
|
||||
elsif ( $ref eq ref qr// ) {
|
||||
Carp::confess("Cannot delegate methods based on a Regexp without a type constraint (isa)")
|
||||
unless $args->{isa};
|
||||
my $target_class = $args->{isa};
|
||||
$kv = {
|
||||
map { $_, $_ }
|
||||
grep { $_ =~ $handles }
|
||||
grep { !exists $Mo::Object::{$_} && $target_class->can($_) }
|
||||
grep { !$Mo::Internal::Keyword{$_} }
|
||||
keys %{ _stash_for $target_class }
|
||||
};
|
||||
}
|
||||
else {
|
||||
Carp::confess("handles for $ref not yet implemented");
|
||||
}
|
||||
|
||||
while ( my ($method, $target) = each %{$kv} ) {
|
||||
my $name = _glob_for "${caller}::$method";
|
||||
Carp::confess("You cannot overwrite a locally defined method ($method) with a delegation")
|
||||
if defined &$name;
|
||||
|
||||
my ($target, @curried_args) = ref($target) ? @$target : $target;
|
||||
*$name = sub {
|
||||
my $self = shift;
|
||||
my $delegate_to = $self->$attribute();
|
||||
my $error = "Cannot delegate $method to $target because the value of $attribute";
|
||||
Carp::confess("$error is not defined") unless $delegate_to;
|
||||
Carp::confess("$error is not an object (got '$delegate_to')")
|
||||
unless Scalar::Util::blessed($delegate_to) || (!ref($delegate_to) && $delegate_to->can($target));
|
||||
return $delegate_to->$target(@curried_args, @_);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub _nested_constraints {
|
||||
my ($attribute, $aggregate_type, $type) = @_;
|
||||
|
||||
my $inner_types;
|
||||
if ( $type =~ /\A(ArrayRef|Maybe)\[(.*)\]\z/ ) {
|
||||
$inner_types = _nested_constraints($1, $2);
|
||||
}
|
||||
else {
|
||||
$inner_types = $TYPES{$type};
|
||||
}
|
||||
|
||||
if ( $aggregate_type eq 'ArrayRef' ) {
|
||||
return sub {
|
||||
my ($val) = @_;
|
||||
return unless ref($val) eq ref([]);
|
||||
|
||||
if ($inner_types) {
|
||||
for my $value ( @{$val} ) {
|
||||
return unless $inner_types->($value)
|
||||
}
|
||||
}
|
||||
else {
|
||||
for my $value ( @{$val} ) {
|
||||
return unless $value && ($value eq $type
|
||||
|| (Scalar::Util::blessed($value) && $value->isa($type)));
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
};
|
||||
}
|
||||
elsif ( $aggregate_type eq 'Maybe' ) {
|
||||
return sub {
|
||||
my ($value) = @_;
|
||||
return 1 if ! defined($value);
|
||||
if ($inner_types) {
|
||||
return unless $inner_types->($value)
|
||||
}
|
||||
else {
|
||||
return unless $value eq $type
|
||||
|| (Scalar::Util::blessed($value) && $value->isa($type));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
Carp::confess("Nested aggregate types are only implemented for ArrayRefs and Maybe");
|
||||
}
|
||||
}
|
||||
|
||||
sub _set_package_isa {
|
||||
my ($package, @new_isa) = @_;
|
||||
|
||||
*{ _glob_for "${package}::ISA" } = [@new_isa];
|
||||
}
|
||||
|
||||
sub _set_inherited_metadata {
|
||||
my $class = shift;
|
||||
my $linearized_isa = mro::get_linear_isa($class);
|
||||
my %new_metadata;
|
||||
|
||||
for my $isa_class (reverse @$linearized_isa) {
|
||||
%new_metadata = (
|
||||
%new_metadata,
|
||||
%{ $metadata_for{$isa_class} || {} },
|
||||
);
|
||||
}
|
||||
$metadata_for{$class} = \%new_metadata;
|
||||
}
|
||||
|
||||
sub unimport {
|
||||
my $caller = scalar caller();
|
||||
my $stash = _stash_for( $caller );
|
||||
|
||||
delete $stash->{$_} for @{$export_for{$caller}};
|
||||
}
|
||||
|
||||
sub Dumper {
|
||||
require Data::Dumper;
|
||||
local $Data::Dumper::Indent = 0;
|
||||
local $Data::Dumper::Sortkeys = 0;
|
||||
local $Data::Dumper::Quotekeys = 0;
|
||||
local $Data::Dumper::Terse = 1;
|
||||
|
||||
Data::Dumper::Dumper(@_)
|
||||
}
|
||||
|
||||
BEGIN {
|
||||
if ($] >= 5.010) {
|
||||
{ local $@; require mro; }
|
||||
}
|
||||
else {
|
||||
local $@;
|
||||
eval {
|
||||
require MRO::Compat;
|
||||
} or do {
|
||||
*mro::get_linear_isa = *mro::get_linear_isa_dfs = sub {
|
||||
no strict 'refs';
|
||||
|
||||
my $classname = shift;
|
||||
|
||||
my @lin = ($classname);
|
||||
my %stored;
|
||||
foreach my $parent (@{"$classname\::ISA"}) {
|
||||
my $plin = mro::get_linear_isa_dfs($parent);
|
||||
foreach (@$plin) {
|
||||
next if exists $stored{$_};
|
||||
push(@lin, $_);
|
||||
$stored{$_} = 1;
|
||||
}
|
||||
}
|
||||
return \@lin;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub override {
|
||||
my ($methods, $code) = @_;
|
||||
my $caller = scalar caller;
|
||||
|
||||
for my $method ( ref($methods) ? @$methods : $methods ) {
|
||||
my $full_method = "${caller}::${method}";
|
||||
*{_glob_for $full_method} = $code;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
1;
|
||||
}
|
||||
# ###########################################################################
|
||||
# End Mo package
|
||||
# ###########################################################################
|
||||
|
||||
# ###########################################################################
|
||||
# OptionParser package
|
||||
# This package is a copy without comments from the original. The original
|
||||
@@ -2641,8 +3106,7 @@ sub _d {
|
||||
{
|
||||
package ReportFormatter;
|
||||
|
||||
use strict;
|
||||
use warnings FATAL => 'all';
|
||||
use Mo;
|
||||
use English qw(-no_match_vars);
|
||||
use constant PTDEBUG => $ENV{PTDEBUG} || 0;
|
||||
|
||||
@@ -2652,40 +3116,102 @@ use POSIX qw(ceil);
|
||||
eval { require Term::ReadKey };
|
||||
my $have_term = $EVAL_ERROR ? 0 : 1;
|
||||
|
||||
sub new {
|
||||
my ( $class, %args ) = @_;
|
||||
my @required_args = qw();
|
||||
foreach my $arg ( @required_args ) {
|
||||
die "I need a $arg argument" unless $args{$arg};
|
||||
}
|
||||
my $self = {
|
||||
underline_header => 1,
|
||||
line_prefix => '# ',
|
||||
line_width => 78,
|
||||
column_spacing => ' ',
|
||||
extend_right => 0,
|
||||
truncate_line_mark => '...',
|
||||
column_errors => 'warn',
|
||||
truncate_header_side => 'left',
|
||||
strip_whitespace => 1,
|
||||
%args, # args above can be overriden, args below cannot
|
||||
n_cols => 0,
|
||||
};
|
||||
|
||||
if ( ($self->{line_width} || '') eq 'auto' ) {
|
||||
has underline_header => (
|
||||
is => 'ro',
|
||||
isa => 'Bool',
|
||||
default => sub { 1 },
|
||||
);
|
||||
has line_prefix => (
|
||||
is => 'ro',
|
||||
isa => 'Str',
|
||||
default => sub { '# ' },
|
||||
);
|
||||
has line_width => (
|
||||
is => 'ro',
|
||||
isa => 'Int',
|
||||
default => sub { 78 },
|
||||
);
|
||||
has column_spacing => (
|
||||
is => 'ro',
|
||||
isa => 'Str',
|
||||
default => sub { ' ' },
|
||||
);
|
||||
has extend_right => (
|
||||
is => 'ro',
|
||||
isa => 'Bool',
|
||||
default => sub { '' },
|
||||
);
|
||||
has truncate_line_mark => (
|
||||
is => 'ro',
|
||||
isa => 'Str',
|
||||
default => sub { '...' },
|
||||
);
|
||||
has column_errors => (
|
||||
is => 'ro',
|
||||
isa => 'Str',
|
||||
default => sub { 'warn' },
|
||||
);
|
||||
has truncate_header_side => (
|
||||
is => 'ro',
|
||||
isa => 'Str',
|
||||
default => sub { 'left' },
|
||||
);
|
||||
has strip_whitespace => (
|
||||
is => 'ro',
|
||||
isa => 'Bool',
|
||||
default => sub { 1 },
|
||||
);
|
||||
has title => (
|
||||
is => 'rw',
|
||||
isa => 'Str',
|
||||
predicate => 'has_title',
|
||||
);
|
||||
|
||||
|
||||
has n_cols => (
|
||||
is => 'rw',
|
||||
isa => 'Int',
|
||||
default => sub { 0 },
|
||||
init_arg => undef,
|
||||
);
|
||||
|
||||
has cols => (
|
||||
is => 'ro',
|
||||
isa => 'ArrayRef',
|
||||
init_arg => undef,
|
||||
default => sub { [] },
|
||||
clearer => 'clear_cols',
|
||||
);
|
||||
|
||||
has lines => (
|
||||
is => 'ro',
|
||||
isa => 'ArrayRef',
|
||||
init_arg => undef,
|
||||
default => sub { [] },
|
||||
clearer => 'clear_lines',
|
||||
);
|
||||
|
||||
has truncate_headers => (
|
||||
is => 'rw',
|
||||
isa => 'Bool',
|
||||
default => sub { undef },
|
||||
init_arg => undef,
|
||||
clearer => 'clear_truncate_headers',
|
||||
);
|
||||
|
||||
sub BUILDARGS {
|
||||
my $class = shift;
|
||||
my $args = $class->SUPER::BUILDARGS(@_);
|
||||
|
||||
if ( ($args->{line_width} || '') eq 'auto' ) {
|
||||
die "Cannot auto-detect line width because the Term::ReadKey module "
|
||||
. "is not installed" unless $have_term;
|
||||
($self->{line_width}) = GetTerminalSize();
|
||||
($args->{line_width}) = GetTerminalSize();
|
||||
PTDEBUG && _d('Line width:', $args->{line_width});
|
||||
}
|
||||
PTDEBUG && _d('Line width:', $self->{line_width});
|
||||
|
||||
return bless $self, $class;
|
||||
}
|
||||
|
||||
sub set_title {
|
||||
my ( $self, $title ) = @_;
|
||||
$self->{title} = $title;
|
||||
return;
|
||||
return $args;
|
||||
}
|
||||
|
||||
sub set_columns {
|
||||
@@ -2701,7 +3227,7 @@ sub set_columns {
|
||||
die "Column does not have a name" unless defined $col_name;
|
||||
|
||||
if ( $col->{width} ) {
|
||||
$col->{width_pct} = ceil(($col->{width} * 100) / $self->{line_width});
|
||||
$col->{width_pct} = ceil(($col->{width} * 100) / $self->line_width());
|
||||
PTDEBUG && _d('col:', $col_name, 'width:', $col->{width}, 'chars =',
|
||||
$col->{width_pct}, '%');
|
||||
}
|
||||
@@ -2728,10 +3254,10 @@ sub set_columns {
|
||||
|
||||
$col->{right_most} = 1 if $i == $#cols;
|
||||
|
||||
push @{$self->{cols}}, $col;
|
||||
push @{$self->cols}, $col;
|
||||
}
|
||||
|
||||
$self->{n_cols} = scalar @cols;
|
||||
$self->n_cols( scalar @cols );
|
||||
|
||||
if ( ($used_width || 0) > 100 ) {
|
||||
die "Total width_pct for all columns is >100%";
|
||||
@@ -2741,15 +3267,15 @@ sub set_columns {
|
||||
my $wid_per_col = int((100 - $used_width) / scalar @auto_width_cols);
|
||||
PTDEBUG && _d('Line width left:', (100-$used_width), '%;',
|
||||
'each auto width col:', $wid_per_col, '%');
|
||||
map { $self->{cols}->[$_]->{width_pct} = $wid_per_col } @auto_width_cols;
|
||||
map { $self->cols->[$_]->{width_pct} = $wid_per_col } @auto_width_cols;
|
||||
}
|
||||
|
||||
$min_hdr_wid += ($self->{n_cols} - 1) * length $self->{column_spacing};
|
||||
$min_hdr_wid += ($self->n_cols() - 1) * length $self->column_spacing();
|
||||
PTDEBUG && _d('min header width:', $min_hdr_wid);
|
||||
if ( $min_hdr_wid > $self->{line_width} ) {
|
||||
if ( $min_hdr_wid > $self->line_width() ) {
|
||||
PTDEBUG && _d('Will truncate headers because min header width',
|
||||
$min_hdr_wid, '> line width', $self->{line_width});
|
||||
$self->{truncate_headers} = 1;
|
||||
$min_hdr_wid, '> line width', $self->line_width());
|
||||
$self->truncate_headers(1);
|
||||
}
|
||||
|
||||
return;
|
||||
@@ -2758,14 +3284,14 @@ sub set_columns {
|
||||
sub add_line {
|
||||
my ( $self, @vals ) = @_;
|
||||
my $n_vals = scalar @vals;
|
||||
if ( $n_vals != $self->{n_cols} ) {
|
||||
if ( $n_vals != $self->n_cols() ) {
|
||||
$self->_column_error("Number of values $n_vals does not match "
|
||||
. "number of columns $self->{n_cols}");
|
||||
. "number of columns " . $self->n_cols());
|
||||
}
|
||||
for my $i ( 0..($n_vals-1) ) {
|
||||
my $col = $self->{cols}->[$i];
|
||||
my $col = $self->cols->[$i];
|
||||
my $val = defined $vals[$i] ? $vals[$i] : $col->{undef_value};
|
||||
if ( $self->{strip_whitespace} ) {
|
||||
if ( $self->strip_whitespace() ) {
|
||||
$val =~ s/^\s+//g;
|
||||
$val =~ s/\s+$//;
|
||||
$vals[$i] = $val;
|
||||
@@ -2774,7 +3300,7 @@ sub add_line {
|
||||
$col->{min_val} = min($width, ($col->{min_val} || $width));
|
||||
$col->{max_val} = max($width, ($col->{max_val} || $width));
|
||||
}
|
||||
push @{$self->{lines}}, \@vals;
|
||||
push @{$self->lines}, \@vals;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2782,26 +3308,28 @@ sub get_report {
|
||||
my ( $self, %args ) = @_;
|
||||
|
||||
$self->_calculate_column_widths();
|
||||
$self->_truncate_headers() if $self->{truncate_headers};
|
||||
if ( $self->truncate_headers() ) {
|
||||
$self->_truncate_headers();
|
||||
}
|
||||
$self->_truncate_line_values(%args);
|
||||
|
||||
my @col_fmts = $self->_make_column_formats();
|
||||
my $fmt = ($self->{line_prefix} || '')
|
||||
. join($self->{column_spacing}, @col_fmts);
|
||||
my $fmt = $self->line_prefix()
|
||||
. join($self->column_spacing(), @col_fmts);
|
||||
PTDEBUG && _d('Format:', $fmt);
|
||||
|
||||
(my $hdr_fmt = $fmt) =~ s/%([^-])/%-$1/g;
|
||||
|
||||
my @lines;
|
||||
push @lines, sprintf "$self->{line_prefix}$self->{title}" if $self->{title};
|
||||
push @lines, $self->line_prefix() . $self->title() if $self->has_title();
|
||||
push @lines, $self->_truncate_line(
|
||||
sprintf($hdr_fmt, map { $_->{name} } @{$self->{cols}}),
|
||||
sprintf($hdr_fmt, map { $_->{name} } @{$self->cols}),
|
||||
strip => 1,
|
||||
mark => '',
|
||||
);
|
||||
|
||||
if ( $self->{underline_header} ) {
|
||||
my @underlines = map { '=' x $_->{print_width} } @{$self->{cols}};
|
||||
if ( $self->underline_header() ) {
|
||||
my @underlines = map { '=' x $_->{print_width} } @{$self->cols};
|
||||
push @lines, $self->_truncate_line(
|
||||
sprintf($fmt, map { $_ || '' } @underlines),
|
||||
mark => '',
|
||||
@@ -2812,19 +3340,23 @@ sub get_report {
|
||||
my $vals = $_;
|
||||
my $i = 0;
|
||||
my @vals = map {
|
||||
my $val = defined $_ ? $_ : $self->{cols}->[$i++]->{undef_value};
|
||||
my $val = defined $_ ? $_ : $self->cols->[$i++]->{undef_value};
|
||||
$val = '' if !defined $val;
|
||||
$val =~ s/\n/ /g;
|
||||
$val;
|
||||
} @$vals;
|
||||
my $line = sprintf($fmt, @vals);
|
||||
if ( $self->{extend_right} ) {
|
||||
if ( $self->extend_right() ) {
|
||||
$line;
|
||||
}
|
||||
else {
|
||||
$self->_truncate_line($line);
|
||||
}
|
||||
} @{$self->{lines}};
|
||||
} @{$self->lines};
|
||||
|
||||
$self->clear_cols();
|
||||
$self->clear_lines();
|
||||
$self->clear_truncate_headers();
|
||||
|
||||
return join("\n", @lines) . "\n";
|
||||
}
|
||||
@@ -2832,7 +3364,7 @@ sub get_report {
|
||||
sub truncate_value {
|
||||
my ( $self, $col, $val, $width, $side ) = @_;
|
||||
return $val if length $val <= $width;
|
||||
return $val if $col->{right_most} && $self->{extend_right};
|
||||
return $val if $col->{right_most} && $self->extend_right();
|
||||
$side ||= $col->{truncate_side};
|
||||
my $mark = $col->{truncate_mark};
|
||||
if ( $side eq 'right' ) {
|
||||
@@ -2852,8 +3384,8 @@ sub _calculate_column_widths {
|
||||
my ( $self ) = @_;
|
||||
|
||||
my $extra_space = 0;
|
||||
foreach my $col ( @{$self->{cols}} ) {
|
||||
my $print_width = int($self->{line_width} * ($col->{width_pct} / 100));
|
||||
foreach my $col ( @{$self->cols} ) {
|
||||
my $print_width = int($self->line_width() * ($col->{width_pct} / 100));
|
||||
|
||||
PTDEBUG && _d('col:', $col->{name}, 'width pct:', $col->{width_pct},
|
||||
'char width:', $print_width,
|
||||
@@ -2877,7 +3409,7 @@ sub _calculate_column_widths {
|
||||
|
||||
PTDEBUG && _d('Extra space:', $extra_space);
|
||||
while ( $extra_space-- ) {
|
||||
foreach my $col ( @{$self->{cols}} ) {
|
||||
foreach my $col ( @{$self->cols} ) {
|
||||
if ( $col->{auto_width}
|
||||
&& ( $col->{print_width} < $col->{max_val}
|
||||
|| $col->{print_width} < $col->{header_width})
|
||||
@@ -2892,8 +3424,8 @@ sub _calculate_column_widths {
|
||||
|
||||
sub _truncate_headers {
|
||||
my ( $self, $col ) = @_;
|
||||
my $side = $self->{truncate_header_side};
|
||||
foreach my $col ( @{$self->{cols}} ) {
|
||||
my $side = $self->truncate_header_side();
|
||||
foreach my $col ( @{$self->cols} ) {
|
||||
my $col_name = $col->{name};
|
||||
my $print_width = $col->{print_width};
|
||||
next if length $col_name <= $print_width;
|
||||
@@ -2906,10 +3438,10 @@ sub _truncate_headers {
|
||||
|
||||
sub _truncate_line_values {
|
||||
my ( $self, %args ) = @_;
|
||||
my $n_vals = $self->{n_cols} - 1;
|
||||
foreach my $vals ( @{$self->{lines}} ) {
|
||||
my $n_vals = $self->n_cols() - 1;
|
||||
foreach my $vals ( @{$self->lines} ) {
|
||||
for my $i ( 0..$n_vals ) {
|
||||
my $col = $self->{cols}->[$i];
|
||||
my $col = $self->cols->[$i];
|
||||
my $val = defined $vals->[$i] ? $vals->[$i] : $col->{undef_value};
|
||||
my $width = length $val;
|
||||
|
||||
@@ -2935,9 +3467,9 @@ sub _truncate_line_values {
|
||||
sub _make_column_formats {
|
||||
my ( $self ) = @_;
|
||||
my @col_fmts;
|
||||
my $n_cols = $self->{n_cols} - 1;
|
||||
my $n_cols = $self->n_cols() - 1;
|
||||
for my $i ( 0..$n_cols ) {
|
||||
my $col = $self->{cols}->[$i];
|
||||
my $col = $self->cols->[$i];
|
||||
|
||||
my $width = $col->{right_most} && !$col->{right_justify} ? ''
|
||||
: $col->{print_width};
|
||||
@@ -2950,12 +3482,12 @@ sub _make_column_formats {
|
||||
|
||||
sub _truncate_line {
|
||||
my ( $self, $line, %args ) = @_;
|
||||
my $mark = defined $args{mark} ? $args{mark} : $self->{truncate_line_mark};
|
||||
my $mark = defined $args{mark} ? $args{mark} : $self->truncate_line_mark();
|
||||
if ( $line ) {
|
||||
$line =~ s/\s+$// if $args{strip};
|
||||
my $len = length($line);
|
||||
if ( $len > $self->{line_width} ) {
|
||||
$line = substr($line, 0, $self->{line_width} - length $mark);
|
||||
if ( $len > $self->line_width() ) {
|
||||
$line = substr($line, 0, $self->line_width() - length $mark);
|
||||
$line .= $mark if $mark;
|
||||
}
|
||||
}
|
||||
@@ -2965,7 +3497,7 @@ sub _truncate_line {
|
||||
sub _column_error {
|
||||
my ( $self, $err ) = @_;
|
||||
my $msg = "Column error: $err";
|
||||
$self->{column_errors} eq 'die' ? die $msg : warn $msg;
|
||||
$self->column_errors() eq 'die' ? die $msg : warn $msg;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -4443,7 +4975,7 @@ sub main {
|
||||
foreach my $var ( sort keys %$diffs ) {
|
||||
$report->add_line($var, @{$diffs->{$var}});
|
||||
}
|
||||
$report->set_title(
|
||||
$report->title(
|
||||
"$n_diffs config difference" . ($n_diffs > 1 ? 's' : ''));
|
||||
print $report->get_report();
|
||||
}
|
||||
@@ -4853,8 +5385,7 @@ L<http://www.percona.com/software/> for more software developed by Percona.
|
||||
|
||||
=head1 COPYRIGHT, LICENSE, AND WARRANTY
|
||||
|
||||
This program is copyright 2011-2012 Percona Inc.
|
||||
Feedback and improvements are welcome.
|
||||
This program is copyright 2011-2013 Percona Ireland Ltd.
|
||||
|
||||
THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
@@ -4872,6 +5403,6 @@ Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
pt-config-diff 2.1.7
|
||||
pt-config-diff 2.1.8
|
||||
|
||||
=cut
|
||||
|
@@ -36,7 +36,7 @@ BEGIN {
|
||||
# ###########################################################################
|
||||
{
|
||||
package Percona::Toolkit;
|
||||
our $VERSION = '2.1.7';
|
||||
our $VERSION = '2.1.8';
|
||||
|
||||
1;
|
||||
}
|
||||
@@ -4766,8 +4766,8 @@ L<http://www.percona.com/software/> for more software developed by Percona.
|
||||
|
||||
=head1 COPYRIGHT, LICENSE, AND WARRANTY
|
||||
|
||||
This program is copyright 2007-2011 Baron Schwartz, 2011-2012 Percona Inc.
|
||||
Feedback and improvements are welcome.
|
||||
This program is copyright 2011-2013 Percona Ireland Ltd,
|
||||
2007-2011 Baron Schwartz.
|
||||
|
||||
THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
@@ -4785,6 +4785,6 @@ Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
pt-deadlock-logger 2.1.7
|
||||
pt-deadlock-logger 2.1.8
|
||||
|
||||
=cut
|
||||
|
@@ -38,7 +38,7 @@ BEGIN {
|
||||
# ###########################################################################
|
||||
{
|
||||
package Percona::Toolkit;
|
||||
our $VERSION = '2.1.7';
|
||||
our $VERSION = '2.1.8';
|
||||
|
||||
1;
|
||||
}
|
||||
@@ -1240,6 +1240,9 @@ sub parse_timestamp {
|
||||
. (defined $f ? '%09.6f' : '%02d'),
|
||||
$y + 2000, $m, $d, $h, $i, (defined $f ? $s + $f : $s);
|
||||
}
|
||||
elsif ( $val =~ m/^$proper_ts$/ ) {
|
||||
return $val;
|
||||
}
|
||||
return $val;
|
||||
}
|
||||
|
||||
@@ -5548,8 +5551,8 @@ L<http://www.percona.com/software/> for more software developed by Percona.
|
||||
|
||||
=head1 COPYRIGHT, LICENSE, AND WARRANTY
|
||||
|
||||
This program is copyright 2010-2011 Baron Schwartz, 2011-2012 Percona Inc.
|
||||
Feedback and improvements are welcome.
|
||||
This program is copyright 2011-2013 Percona Ireland Ltd,
|
||||
2010-2011 Baron Schwartz.
|
||||
|
||||
THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
@@ -5567,6 +5570,6 @@ Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
pt-diskstats 2.1.7
|
||||
pt-diskstats 2.1.8
|
||||
|
||||
=cut
|
||||
|
@@ -39,7 +39,7 @@ BEGIN {
|
||||
# ###########################################################################
|
||||
{
|
||||
package Percona::Toolkit;
|
||||
our $VERSION = '2.1.7';
|
||||
our $VERSION = '2.1.8';
|
||||
|
||||
1;
|
||||
}
|
||||
@@ -5416,8 +5416,8 @@ L<http://www.percona.com/software/> for more software developed by Percona.
|
||||
|
||||
=head1 COPYRIGHT, LICENSE, AND WARRANTY
|
||||
|
||||
This program is copyright 2007-2011 Baron Schwartz, 2011-2012 Percona Inc.
|
||||
Feedback and improvements are welcome.
|
||||
This program is copyright 2011-2013 Percona Ireland Ltd,
|
||||
2007-2011 Baron Schwartz.
|
||||
|
||||
THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
@@ -5435,6 +5435,6 @@ Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
pt-duplicate-key-checker 2.1.7
|
||||
pt-duplicate-key-checker 2.1.8
|
||||
|
||||
=cut
|
||||
|
@@ -1549,8 +1549,8 @@ L<http://www.percona.com/software/> for more software developed by Percona.
|
||||
|
||||
=head1 COPYRIGHT, LICENSE, AND WARRANTY
|
||||
|
||||
This program is copyright 2007-2011 Baron Schwartz, 2011-2012 Percona Inc.
|
||||
Feedback and improvements are welcome.
|
||||
This program is copyright 2011-2013 Percona Ireland Ltd,
|
||||
2007-2011 Baron Schwartz.
|
||||
|
||||
THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
@@ -1568,6 +1568,6 @@ Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
pt-fifo-split 2.1.7
|
||||
pt-fifo-split 2.1.8
|
||||
|
||||
=cut
|
||||
|
@@ -35,7 +35,7 @@ BEGIN {
|
||||
# ###########################################################################
|
||||
{
|
||||
package Percona::Toolkit;
|
||||
our $VERSION = '2.1.7';
|
||||
our $VERSION = '2.1.8';
|
||||
|
||||
1;
|
||||
}
|
||||
@@ -4879,8 +4879,8 @@ L<http://www.percona.com/software/> for more software developed by Percona.
|
||||
|
||||
=head1 COPYRIGHT, LICENSE, AND WARRANTY
|
||||
|
||||
This program is copyright 2007-2011 Baron Schwartz, 2011-2012 Percona Inc.
|
||||
Feedback and improvements are welcome.
|
||||
This program is copyright 2011-2013 Percona Ireland Ltd,
|
||||
2007-2011 Baron Schwartz.
|
||||
|
||||
THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
@@ -4898,6 +4898,6 @@ Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
pt-find 2.1.7
|
||||
pt-find 2.1.8
|
||||
|
||||
=cut
|
||||
|
@@ -2129,8 +2129,7 @@ L<http://www.percona.com/software/> for more software developed by Percona.
|
||||
|
||||
=head1 COPYRIGHT, LICENSE, AND WARRANTY
|
||||
|
||||
This program is copyright 2011-2012 Percona Inc.
|
||||
Feedback and improvements are welcome.
|
||||
This program is copyright 2011-2012 Percona Ireland Ltd.
|
||||
|
||||
THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
@@ -2148,6 +2147,6 @@ Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
pt-fingerprint 2.1.7
|
||||
pt-fingerprint 2.1.8
|
||||
|
||||
=cut
|
||||
|
@@ -35,7 +35,7 @@ BEGIN {
|
||||
# ###########################################################################
|
||||
{
|
||||
package Percona::Toolkit;
|
||||
our $VERSION = '2.1.7';
|
||||
our $VERSION = '2.1.8';
|
||||
|
||||
1;
|
||||
}
|
||||
@@ -4011,8 +4011,7 @@ L<http://www.percona.com/software/> for more software developed by Percona.
|
||||
|
||||
=head1 COPYRIGHT, LICENSE, AND WARRANTY
|
||||
|
||||
This program is copyright 2011-2012 Percona Inc.
|
||||
Feedback and improvements are welcome.
|
||||
This program is copyright 2011-2012 Percona Ireland Ltd.
|
||||
|
||||
THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
@@ -4030,6 +4029,6 @@ Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
pt-fk-error-logger 2.1.7
|
||||
pt-fk-error-logger 2.1.8
|
||||
|
||||
=cut
|
||||
|
@@ -38,7 +38,7 @@ BEGIN {
|
||||
# ###########################################################################
|
||||
{
|
||||
package Percona::Toolkit;
|
||||
our $VERSION = '2.1.7';
|
||||
our $VERSION = '2.1.8';
|
||||
|
||||
1;
|
||||
}
|
||||
@@ -3168,6 +3168,9 @@ sub parse_timestamp {
|
||||
. (defined $f ? '%09.6f' : '%02d'),
|
||||
$y + 2000, $m, $d, $h, $i, (defined $f ? $s + $f : $s);
|
||||
}
|
||||
elsif ( $val =~ m/^$proper_ts$/ ) {
|
||||
return $val;
|
||||
}
|
||||
return $val;
|
||||
}
|
||||
|
||||
@@ -6023,9 +6026,8 @@ L<http://www.percona.com/software/> for more software developed by Percona.
|
||||
|
||||
=head1 COPYRIGHT, LICENSE, AND WARRANTY
|
||||
|
||||
This program is copyright 2006 Proven Scaling LLC and Six Apart Ltd,
|
||||
2007-2012 Percona Inc.
|
||||
Feedback and improvements are welcome.
|
||||
This program is copyright 2007-2013 Percona Ireland Ltd,
|
||||
2006 Proven Scaling LLC and Six Apart Ltd.
|
||||
|
||||
Feedback and improvements are welcome.
|
||||
|
||||
@@ -6045,6 +6047,6 @@ Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
pt-heartbeat 2.1.7
|
||||
pt-heartbeat 2.1.8
|
||||
|
||||
=cut
|
||||
|
@@ -45,7 +45,7 @@ BEGIN {
|
||||
# ###########################################################################
|
||||
{
|
||||
package Percona::Toolkit;
|
||||
our $VERSION = '2.1.7';
|
||||
our $VERSION = '2.1.8';
|
||||
|
||||
1;
|
||||
}
|
||||
@@ -2713,14 +2713,25 @@ sub parse_event {
|
||||
|
||||
if ( !$found_arg && $pos == $len ) {
|
||||
PTDEBUG && _d("Did not find arg, looking for special cases");
|
||||
local $INPUT_RECORD_SEPARATOR = ";\n";
|
||||
local $INPUT_RECORD_SEPARATOR = ";\n"; # get next line
|
||||
if ( defined(my $l = $next_event->()) ) {
|
||||
chomp $l;
|
||||
$l =~ s/^\s+//;
|
||||
PTDEBUG && _d("Found admin statement", $l);
|
||||
push @properties, 'cmd', 'Admin', 'arg', $l;
|
||||
push @properties, 'bytes', length($properties[-1]);
|
||||
$found_arg++;
|
||||
if ( $l =~ /^\s*[A-Z][a-z_]+: / ) {
|
||||
PTDEBUG && _d("Found NULL query before", $l);
|
||||
local $INPUT_RECORD_SEPARATOR = ";\n#";
|
||||
my $rest_of_event = $next_event->();
|
||||
push @{$self->{pending}}, $l . $rest_of_event;
|
||||
push @properties, 'cmd', 'Query', 'arg', '/* No query */';
|
||||
push @properties, 'bytes', 0;
|
||||
$found_arg++;
|
||||
}
|
||||
else {
|
||||
chomp $l;
|
||||
$l =~ s/^\s+//;
|
||||
PTDEBUG && _d("Found admin statement", $l);
|
||||
push @properties, 'cmd', 'Admin', 'arg', $l;
|
||||
push @properties, 'bytes', length($properties[-1]);
|
||||
$found_arg++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
PTDEBUG && _d("I can't figure out what to do with this line");
|
||||
@@ -3349,6 +3360,9 @@ sub parse_timestamp {
|
||||
. (defined $f ? '%09.6f' : '%02d'),
|
||||
$y + 2000, $m, $d, $h, $i, (defined $f ? $s + $f : $s);
|
||||
}
|
||||
elsif ( $val =~ m/^$proper_ts$/ ) {
|
||||
return $val;
|
||||
}
|
||||
return $val;
|
||||
}
|
||||
|
||||
@@ -7450,8 +7464,8 @@ L<http://www.percona.com/software/> for more software developed by Percona.
|
||||
|
||||
=head1 COPYRIGHT, LICENSE, AND WARRANTY
|
||||
|
||||
This program is copyright 2010-2011 Baron Schwartz, 2011-2012 Percona Inc.
|
||||
Feedback and improvements are welcome.
|
||||
This program is copyright 2011-2013 Percona Ireland Ltd,
|
||||
2010-2011 Baron Schwartz.
|
||||
|
||||
THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
@@ -7469,6 +7483,6 @@ Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
pt-index-usage 2.1.7
|
||||
pt-index-usage 2.1.8
|
||||
|
||||
=cut
|
||||
|
@@ -69,7 +69,7 @@ PO_DIR="" # Directory with program option spec files
|
||||
usage() {
|
||||
local file="$1"
|
||||
|
||||
local usage=$(grep '^Usage: ' "$file")
|
||||
local usage="$(grep '^Usage: ' "$file")"
|
||||
echo $usage
|
||||
echo
|
||||
echo "For more information, 'man $TOOL' or 'perldoc $file'."
|
||||
@@ -1084,8 +1084,8 @@ L<http://www.percona.com/software/> for more software developed by Percona.
|
||||
|
||||
=head1 COPYRIGHT, LICENSE, AND WARRANTY
|
||||
|
||||
This program is copyright 2010-2011 Baron Schwartz, 2011-2012 Percona Inc.
|
||||
Feedback and improvements are welcome.
|
||||
This program is copyright 2011-2013 Percona Ireland Ltd,
|
||||
2010-2011 Baron Schwartz.
|
||||
|
||||
THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
@@ -1103,7 +1103,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
pt-ioprofile 2.1.7
|
||||
pt-ioprofile 2.1.8
|
||||
|
||||
=cut
|
||||
|
||||
|
11
bin/pt-kill
11
bin/pt-kill
@@ -43,7 +43,7 @@ BEGIN {
|
||||
# ###########################################################################
|
||||
{
|
||||
package Percona::Toolkit;
|
||||
our $VERSION = '2.1.7';
|
||||
our $VERSION = '2.1.8';
|
||||
|
||||
1;
|
||||
}
|
||||
@@ -2275,6 +2275,9 @@ sub parse_timestamp {
|
||||
. (defined $f ? '%09.6f' : '%02d'),
|
||||
$y + 2000, $m, $d, $h, $i, (defined $f ? $s + $f : $s);
|
||||
}
|
||||
elsif ( $val =~ m/^$proper_ts$/ ) {
|
||||
return $val;
|
||||
}
|
||||
return $val;
|
||||
}
|
||||
|
||||
@@ -7767,8 +7770,8 @@ L<http://www.percona.com/software/> for more software developed by Percona.
|
||||
|
||||
=head1 COPYRIGHT, LICENSE, AND WARRANTY
|
||||
|
||||
This program is copyright 2009-2011 Baron Schwartz, 2011-2012 Percona Inc.
|
||||
Feedback and improvements are welcome.
|
||||
This program is copyright 2011-2013 Percona Ireland Ltd,
|
||||
2009-2011 Baron Schwartz.
|
||||
|
||||
THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
@@ -7786,6 +7789,6 @@ Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
pt-kill 2.1.7
|
||||
pt-kill 2.1.8
|
||||
|
||||
=cut
|
||||
|
@@ -263,8 +263,8 @@ L<http://www.percona.com/software/> for more software developed by Percona.
|
||||
|
||||
=head1 COPYRIGHT, LICENSE, AND WARRANTY
|
||||
|
||||
This program is copyright 2010 Baron Schwartz, 2011-2012 Percona Inc.
|
||||
Feedback and improvements are welcome.
|
||||
This program is copyright 2011-2013 Percona Ireland Ltd,
|
||||
2010 Baron Schwartz.
|
||||
|
||||
THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
@@ -282,7 +282,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
pt-mext 2.1.7
|
||||
pt-mext 2.1.8
|
||||
|
||||
=cut
|
||||
|
||||
|
@@ -2983,8 +2983,8 @@ L<http://www.percona.com/software/> for more software developed by Percona.
|
||||
|
||||
=head1 COPYRIGHT, LICENSE, AND WARRANTY
|
||||
|
||||
This program is copyright 2010-2011 Baron Schwartz, 2011-2012 Percona Inc.
|
||||
Feedback and improvements are welcome.
|
||||
This program is copyright 2011-2013 Percona Ireland Ltd,
|
||||
2010-2011 Baron Schwartz.
|
||||
|
||||
THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
@@ -3002,7 +3002,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
pt-mysql-summary 2.1.7
|
||||
pt-mysql-summary 2.1.8
|
||||
|
||||
=cut
|
||||
|
||||
|
@@ -51,7 +51,7 @@ BEGIN {
|
||||
# ###########################################################################
|
||||
{
|
||||
package Percona::Toolkit;
|
||||
our $VERSION = '2.1.7';
|
||||
our $VERSION = '2.1.8';
|
||||
|
||||
1;
|
||||
}
|
||||
@@ -1232,6 +1232,7 @@ sub Mo::import {
|
||||
_set_package_isa($caller, @_);
|
||||
_set_inherited_metadata($caller);
|
||||
},
|
||||
override => \&override,
|
||||
has => sub {
|
||||
my $names = shift;
|
||||
for my $attribute ( ref $names ? @$names : $names ) {
|
||||
@@ -1528,6 +1529,16 @@ BEGIN {
|
||||
}
|
||||
}
|
||||
|
||||
sub override {
|
||||
my ($methods, $code) = @_;
|
||||
my $caller = scalar caller;
|
||||
|
||||
for my $method ( ref($methods) ? @$methods : $methods ) {
|
||||
my $full_method = "${caller}::${method}";
|
||||
*{_glob_for $full_method} = $code;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
1;
|
||||
}
|
||||
@@ -2319,8 +2330,7 @@ sub _d {
|
||||
{
|
||||
package ReportFormatter;
|
||||
|
||||
use strict;
|
||||
use warnings FATAL => 'all';
|
||||
use Mo;
|
||||
use English qw(-no_match_vars);
|
||||
use constant PTDEBUG => $ENV{PTDEBUG} || 0;
|
||||
|
||||
@@ -2330,40 +2340,102 @@ use POSIX qw(ceil);
|
||||
eval { require Term::ReadKey };
|
||||
my $have_term = $EVAL_ERROR ? 0 : 1;
|
||||
|
||||
sub new {
|
||||
my ( $class, %args ) = @_;
|
||||
my @required_args = qw();
|
||||
foreach my $arg ( @required_args ) {
|
||||
die "I need a $arg argument" unless $args{$arg};
|
||||
}
|
||||
my $self = {
|
||||
underline_header => 1,
|
||||
line_prefix => '# ',
|
||||
line_width => 78,
|
||||
column_spacing => ' ',
|
||||
extend_right => 0,
|
||||
truncate_line_mark => '...',
|
||||
column_errors => 'warn',
|
||||
truncate_header_side => 'left',
|
||||
strip_whitespace => 1,
|
||||
%args, # args above can be overriden, args below cannot
|
||||
n_cols => 0,
|
||||
};
|
||||
|
||||
if ( ($self->{line_width} || '') eq 'auto' ) {
|
||||
has underline_header => (
|
||||
is => 'ro',
|
||||
isa => 'Bool',
|
||||
default => sub { 1 },
|
||||
);
|
||||
has line_prefix => (
|
||||
is => 'ro',
|
||||
isa => 'Str',
|
||||
default => sub { '# ' },
|
||||
);
|
||||
has line_width => (
|
||||
is => 'ro',
|
||||
isa => 'Int',
|
||||
default => sub { 78 },
|
||||
);
|
||||
has column_spacing => (
|
||||
is => 'ro',
|
||||
isa => 'Str',
|
||||
default => sub { ' ' },
|
||||
);
|
||||
has extend_right => (
|
||||
is => 'ro',
|
||||
isa => 'Bool',
|
||||
default => sub { '' },
|
||||
);
|
||||
has truncate_line_mark => (
|
||||
is => 'ro',
|
||||
isa => 'Str',
|
||||
default => sub { '...' },
|
||||
);
|
||||
has column_errors => (
|
||||
is => 'ro',
|
||||
isa => 'Str',
|
||||
default => sub { 'warn' },
|
||||
);
|
||||
has truncate_header_side => (
|
||||
is => 'ro',
|
||||
isa => 'Str',
|
||||
default => sub { 'left' },
|
||||
);
|
||||
has strip_whitespace => (
|
||||
is => 'ro',
|
||||
isa => 'Bool',
|
||||
default => sub { 1 },
|
||||
);
|
||||
has title => (
|
||||
is => 'rw',
|
||||
isa => 'Str',
|
||||
predicate => 'has_title',
|
||||
);
|
||||
|
||||
|
||||
has n_cols => (
|
||||
is => 'rw',
|
||||
isa => 'Int',
|
||||
default => sub { 0 },
|
||||
init_arg => undef,
|
||||
);
|
||||
|
||||
has cols => (
|
||||
is => 'ro',
|
||||
isa => 'ArrayRef',
|
||||
init_arg => undef,
|
||||
default => sub { [] },
|
||||
clearer => 'clear_cols',
|
||||
);
|
||||
|
||||
has lines => (
|
||||
is => 'ro',
|
||||
isa => 'ArrayRef',
|
||||
init_arg => undef,
|
||||
default => sub { [] },
|
||||
clearer => 'clear_lines',
|
||||
);
|
||||
|
||||
has truncate_headers => (
|
||||
is => 'rw',
|
||||
isa => 'Bool',
|
||||
default => sub { undef },
|
||||
init_arg => undef,
|
||||
clearer => 'clear_truncate_headers',
|
||||
);
|
||||
|
||||
sub BUILDARGS {
|
||||
my $class = shift;
|
||||
my $args = $class->SUPER::BUILDARGS(@_);
|
||||
|
||||
if ( ($args->{line_width} || '') eq 'auto' ) {
|
||||
die "Cannot auto-detect line width because the Term::ReadKey module "
|
||||
. "is not installed" unless $have_term;
|
||||
($self->{line_width}) = GetTerminalSize();
|
||||
($args->{line_width}) = GetTerminalSize();
|
||||
PTDEBUG && _d('Line width:', $args->{line_width});
|
||||
}
|
||||
PTDEBUG && _d('Line width:', $self->{line_width});
|
||||
|
||||
return bless $self, $class;
|
||||
}
|
||||
|
||||
sub set_title {
|
||||
my ( $self, $title ) = @_;
|
||||
$self->{title} = $title;
|
||||
return;
|
||||
return $args;
|
||||
}
|
||||
|
||||
sub set_columns {
|
||||
@@ -2379,7 +2451,7 @@ sub set_columns {
|
||||
die "Column does not have a name" unless defined $col_name;
|
||||
|
||||
if ( $col->{width} ) {
|
||||
$col->{width_pct} = ceil(($col->{width} * 100) / $self->{line_width});
|
||||
$col->{width_pct} = ceil(($col->{width} * 100) / $self->line_width());
|
||||
PTDEBUG && _d('col:', $col_name, 'width:', $col->{width}, 'chars =',
|
||||
$col->{width_pct}, '%');
|
||||
}
|
||||
@@ -2406,10 +2478,10 @@ sub set_columns {
|
||||
|
||||
$col->{right_most} = 1 if $i == $#cols;
|
||||
|
||||
push @{$self->{cols}}, $col;
|
||||
push @{$self->cols}, $col;
|
||||
}
|
||||
|
||||
$self->{n_cols} = scalar @cols;
|
||||
$self->n_cols( scalar @cols );
|
||||
|
||||
if ( ($used_width || 0) > 100 ) {
|
||||
die "Total width_pct for all columns is >100%";
|
||||
@@ -2419,15 +2491,15 @@ sub set_columns {
|
||||
my $wid_per_col = int((100 - $used_width) / scalar @auto_width_cols);
|
||||
PTDEBUG && _d('Line width left:', (100-$used_width), '%;',
|
||||
'each auto width col:', $wid_per_col, '%');
|
||||
map { $self->{cols}->[$_]->{width_pct} = $wid_per_col } @auto_width_cols;
|
||||
map { $self->cols->[$_]->{width_pct} = $wid_per_col } @auto_width_cols;
|
||||
}
|
||||
|
||||
$min_hdr_wid += ($self->{n_cols} - 1) * length $self->{column_spacing};
|
||||
$min_hdr_wid += ($self->n_cols() - 1) * length $self->column_spacing();
|
||||
PTDEBUG && _d('min header width:', $min_hdr_wid);
|
||||
if ( $min_hdr_wid > $self->{line_width} ) {
|
||||
if ( $min_hdr_wid > $self->line_width() ) {
|
||||
PTDEBUG && _d('Will truncate headers because min header width',
|
||||
$min_hdr_wid, '> line width', $self->{line_width});
|
||||
$self->{truncate_headers} = 1;
|
||||
$min_hdr_wid, '> line width', $self->line_width());
|
||||
$self->truncate_headers(1);
|
||||
}
|
||||
|
||||
return;
|
||||
@@ -2436,14 +2508,14 @@ sub set_columns {
|
||||
sub add_line {
|
||||
my ( $self, @vals ) = @_;
|
||||
my $n_vals = scalar @vals;
|
||||
if ( $n_vals != $self->{n_cols} ) {
|
||||
if ( $n_vals != $self->n_cols() ) {
|
||||
$self->_column_error("Number of values $n_vals does not match "
|
||||
. "number of columns $self->{n_cols}");
|
||||
. "number of columns " . $self->n_cols());
|
||||
}
|
||||
for my $i ( 0..($n_vals-1) ) {
|
||||
my $col = $self->{cols}->[$i];
|
||||
my $col = $self->cols->[$i];
|
||||
my $val = defined $vals[$i] ? $vals[$i] : $col->{undef_value};
|
||||
if ( $self->{strip_whitespace} ) {
|
||||
if ( $self->strip_whitespace() ) {
|
||||
$val =~ s/^\s+//g;
|
||||
$val =~ s/\s+$//;
|
||||
$vals[$i] = $val;
|
||||
@@ -2452,7 +2524,7 @@ sub add_line {
|
||||
$col->{min_val} = min($width, ($col->{min_val} || $width));
|
||||
$col->{max_val} = max($width, ($col->{max_val} || $width));
|
||||
}
|
||||
push @{$self->{lines}}, \@vals;
|
||||
push @{$self->lines}, \@vals;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2460,26 +2532,28 @@ sub get_report {
|
||||
my ( $self, %args ) = @_;
|
||||
|
||||
$self->_calculate_column_widths();
|
||||
$self->_truncate_headers() if $self->{truncate_headers};
|
||||
if ( $self->truncate_headers() ) {
|
||||
$self->_truncate_headers();
|
||||
}
|
||||
$self->_truncate_line_values(%args);
|
||||
|
||||
my @col_fmts = $self->_make_column_formats();
|
||||
my $fmt = ($self->{line_prefix} || '')
|
||||
. join($self->{column_spacing}, @col_fmts);
|
||||
my $fmt = $self->line_prefix()
|
||||
. join($self->column_spacing(), @col_fmts);
|
||||
PTDEBUG && _d('Format:', $fmt);
|
||||
|
||||
(my $hdr_fmt = $fmt) =~ s/%([^-])/%-$1/g;
|
||||
|
||||
my @lines;
|
||||
push @lines, sprintf "$self->{line_prefix}$self->{title}" if $self->{title};
|
||||
push @lines, $self->line_prefix() . $self->title() if $self->has_title();
|
||||
push @lines, $self->_truncate_line(
|
||||
sprintf($hdr_fmt, map { $_->{name} } @{$self->{cols}}),
|
||||
sprintf($hdr_fmt, map { $_->{name} } @{$self->cols}),
|
||||
strip => 1,
|
||||
mark => '',
|
||||
);
|
||||
|
||||
if ( $self->{underline_header} ) {
|
||||
my @underlines = map { '=' x $_->{print_width} } @{$self->{cols}};
|
||||
if ( $self->underline_header() ) {
|
||||
my @underlines = map { '=' x $_->{print_width} } @{$self->cols};
|
||||
push @lines, $self->_truncate_line(
|
||||
sprintf($fmt, map { $_ || '' } @underlines),
|
||||
mark => '',
|
||||
@@ -2490,19 +2564,23 @@ sub get_report {
|
||||
my $vals = $_;
|
||||
my $i = 0;
|
||||
my @vals = map {
|
||||
my $val = defined $_ ? $_ : $self->{cols}->[$i++]->{undef_value};
|
||||
my $val = defined $_ ? $_ : $self->cols->[$i++]->{undef_value};
|
||||
$val = '' if !defined $val;
|
||||
$val =~ s/\n/ /g;
|
||||
$val;
|
||||
} @$vals;
|
||||
my $line = sprintf($fmt, @vals);
|
||||
if ( $self->{extend_right} ) {
|
||||
if ( $self->extend_right() ) {
|
||||
$line;
|
||||
}
|
||||
else {
|
||||
$self->_truncate_line($line);
|
||||
}
|
||||
} @{$self->{lines}};
|
||||
} @{$self->lines};
|
||||
|
||||
$self->clear_cols();
|
||||
$self->clear_lines();
|
||||
$self->clear_truncate_headers();
|
||||
|
||||
return join("\n", @lines) . "\n";
|
||||
}
|
||||
@@ -2510,7 +2588,7 @@ sub get_report {
|
||||
sub truncate_value {
|
||||
my ( $self, $col, $val, $width, $side ) = @_;
|
||||
return $val if length $val <= $width;
|
||||
return $val if $col->{right_most} && $self->{extend_right};
|
||||
return $val if $col->{right_most} && $self->extend_right();
|
||||
$side ||= $col->{truncate_side};
|
||||
my $mark = $col->{truncate_mark};
|
||||
if ( $side eq 'right' ) {
|
||||
@@ -2530,8 +2608,8 @@ sub _calculate_column_widths {
|
||||
my ( $self ) = @_;
|
||||
|
||||
my $extra_space = 0;
|
||||
foreach my $col ( @{$self->{cols}} ) {
|
||||
my $print_width = int($self->{line_width} * ($col->{width_pct} / 100));
|
||||
foreach my $col ( @{$self->cols} ) {
|
||||
my $print_width = int($self->line_width() * ($col->{width_pct} / 100));
|
||||
|
||||
PTDEBUG && _d('col:', $col->{name}, 'width pct:', $col->{width_pct},
|
||||
'char width:', $print_width,
|
||||
@@ -2555,7 +2633,7 @@ sub _calculate_column_widths {
|
||||
|
||||
PTDEBUG && _d('Extra space:', $extra_space);
|
||||
while ( $extra_space-- ) {
|
||||
foreach my $col ( @{$self->{cols}} ) {
|
||||
foreach my $col ( @{$self->cols} ) {
|
||||
if ( $col->{auto_width}
|
||||
&& ( $col->{print_width} < $col->{max_val}
|
||||
|| $col->{print_width} < $col->{header_width})
|
||||
@@ -2570,8 +2648,8 @@ sub _calculate_column_widths {
|
||||
|
||||
sub _truncate_headers {
|
||||
my ( $self, $col ) = @_;
|
||||
my $side = $self->{truncate_header_side};
|
||||
foreach my $col ( @{$self->{cols}} ) {
|
||||
my $side = $self->truncate_header_side();
|
||||
foreach my $col ( @{$self->cols} ) {
|
||||
my $col_name = $col->{name};
|
||||
my $print_width = $col->{print_width};
|
||||
next if length $col_name <= $print_width;
|
||||
@@ -2584,10 +2662,10 @@ sub _truncate_headers {
|
||||
|
||||
sub _truncate_line_values {
|
||||
my ( $self, %args ) = @_;
|
||||
my $n_vals = $self->{n_cols} - 1;
|
||||
foreach my $vals ( @{$self->{lines}} ) {
|
||||
my $n_vals = $self->n_cols() - 1;
|
||||
foreach my $vals ( @{$self->lines} ) {
|
||||
for my $i ( 0..$n_vals ) {
|
||||
my $col = $self->{cols}->[$i];
|
||||
my $col = $self->cols->[$i];
|
||||
my $val = defined $vals->[$i] ? $vals->[$i] : $col->{undef_value};
|
||||
my $width = length $val;
|
||||
|
||||
@@ -2613,9 +2691,9 @@ sub _truncate_line_values {
|
||||
sub _make_column_formats {
|
||||
my ( $self ) = @_;
|
||||
my @col_fmts;
|
||||
my $n_cols = $self->{n_cols} - 1;
|
||||
my $n_cols = $self->n_cols() - 1;
|
||||
for my $i ( 0..$n_cols ) {
|
||||
my $col = $self->{cols}->[$i];
|
||||
my $col = $self->cols->[$i];
|
||||
|
||||
my $width = $col->{right_most} && !$col->{right_justify} ? ''
|
||||
: $col->{print_width};
|
||||
@@ -2628,12 +2706,12 @@ sub _make_column_formats {
|
||||
|
||||
sub _truncate_line {
|
||||
my ( $self, $line, %args ) = @_;
|
||||
my $mark = defined $args{mark} ? $args{mark} : $self->{truncate_line_mark};
|
||||
my $mark = defined $args{mark} ? $args{mark} : $self->truncate_line_mark();
|
||||
if ( $line ) {
|
||||
$line =~ s/\s+$// if $args{strip};
|
||||
my $len = length($line);
|
||||
if ( $len > $self->{line_width} ) {
|
||||
$line = substr($line, 0, $self->{line_width} - length $mark);
|
||||
if ( $len > $self->line_width() ) {
|
||||
$line = substr($line, 0, $self->line_width() - length $mark);
|
||||
$line .= $mark if $mark;
|
||||
}
|
||||
}
|
||||
@@ -2643,7 +2721,7 @@ sub _truncate_line {
|
||||
sub _column_error {
|
||||
my ( $self, $err ) = @_;
|
||||
my $msg = "Column error: $err";
|
||||
$self->{column_errors} eq 'die' ? die $msg : warn $msg;
|
||||
$self->column_errors() eq 'die' ? die $msg : warn $msg;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -5686,24 +5764,26 @@ use Time::Local qw(timegm timelocal);
|
||||
use Digest::MD5 qw(md5_hex);
|
||||
use B qw();
|
||||
|
||||
require Exporter;
|
||||
our @ISA = qw(Exporter);
|
||||
our %EXPORT_TAGS = ();
|
||||
our @EXPORT = ();
|
||||
our @EXPORT_OK = qw(
|
||||
micro_t
|
||||
percentage_of
|
||||
secs_to_time
|
||||
time_to_secs
|
||||
shorten
|
||||
ts
|
||||
parse_timestamp
|
||||
unix_timestamp
|
||||
any_unix_timestamp
|
||||
make_checksum
|
||||
crc32
|
||||
encode_json
|
||||
);
|
||||
BEGIN {
|
||||
require Exporter;
|
||||
our @ISA = qw(Exporter);
|
||||
our %EXPORT_TAGS = ();
|
||||
our @EXPORT = ();
|
||||
our @EXPORT_OK = qw(
|
||||
micro_t
|
||||
percentage_of
|
||||
secs_to_time
|
||||
time_to_secs
|
||||
shorten
|
||||
ts
|
||||
parse_timestamp
|
||||
unix_timestamp
|
||||
any_unix_timestamp
|
||||
make_checksum
|
||||
crc32
|
||||
encode_json
|
||||
);
|
||||
}
|
||||
|
||||
our $mysql_ts = qr/(\d\d)(\d\d)(\d\d) +(\d+):(\d+):(\d+)(\.\d+)?/;
|
||||
our $proper_ts = qr/(\d\d\d\d)-(\d\d)-(\d\d)[T ](\d\d):(\d\d):(\d\d)(\.\d+)?/;
|
||||
@@ -5835,6 +5915,9 @@ sub parse_timestamp {
|
||||
. (defined $f ? '%09.6f' : '%02d'),
|
||||
$y + 2000, $m, $d, $h, $i, (defined $f ? $s + $f : $s);
|
||||
}
|
||||
elsif ( $val =~ m/^$proper_ts$/ ) {
|
||||
return $val;
|
||||
}
|
||||
return $val;
|
||||
}
|
||||
|
||||
@@ -10830,8 +10913,7 @@ L<http://www.percona.com/software/> for more software developed by Percona.
|
||||
|
||||
=head1 COPYRIGHT, LICENSE, AND WARRANTY
|
||||
|
||||
This program is copyright 2011-2012 Percona Inc.
|
||||
Feedback and improvements are welcome.
|
||||
This program is copyright 2011-2013 Percona Ireland Ltd.
|
||||
|
||||
THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
@@ -10849,6 +10931,6 @@ Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
pt-online-schema-change 2.1.7
|
||||
pt-online-schema-change 2.1.8
|
||||
|
||||
=cut
|
||||
|
@@ -377,8 +377,8 @@ L<http://www.percona.com/software/> for more software developed by Percona.
|
||||
|
||||
=head1 COPYRIGHT, LICENSE, AND WARRANTY
|
||||
|
||||
This program is copyright 2010-2011 Baron Schwartz, 2011-2012 Percona Inc.
|
||||
Feedback and improvements are welcome.
|
||||
This program is copyright 2011-2013 Percona Ireland Ltd,
|
||||
2010-2011 Baron Schwartz.
|
||||
|
||||
THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
@@ -396,7 +396,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
pt-pmp 2.1.7
|
||||
pt-pmp 2.1.8
|
||||
|
||||
=cut
|
||||
|
||||
|
@@ -14,6 +14,7 @@ use warnings FATAL => 'all';
|
||||
BEGIN {
|
||||
$INC{$_} = __FILE__ for map { (my $pkg = "$_.pm") =~ s!::!/!g; $pkg } (qw(
|
||||
Percona::Toolkit
|
||||
Mo
|
||||
DSNParser
|
||||
OptionParser
|
||||
Quoter
|
||||
@@ -46,7 +47,7 @@ BEGIN {
|
||||
# ###########################################################################
|
||||
{
|
||||
package Percona::Toolkit;
|
||||
our $VERSION = '2.1.7';
|
||||
our $VERSION = '2.1.8';
|
||||
|
||||
1;
|
||||
}
|
||||
@@ -54,6 +55,470 @@ our $VERSION = '2.1.7';
|
||||
# End Percona::Toolkit package
|
||||
# ###########################################################################
|
||||
|
||||
# ###########################################################################
|
||||
# Mo package
|
||||
# This package is a copy without comments from the original. The original
|
||||
# with comments and its test file can be found in the Bazaar repository at,
|
||||
# lib/Mo.pm
|
||||
# t/lib/Mo.t
|
||||
# See https://launchpad.net/percona-toolkit for more information.
|
||||
# ###########################################################################
|
||||
{
|
||||
BEGIN {
|
||||
$INC{"Mo.pm"} = __FILE__;
|
||||
package Mo;
|
||||
our $VERSION = '0.30_Percona'; # Forked from 0.30 of Mo.
|
||||
|
||||
{
|
||||
no strict 'refs';
|
||||
sub _glob_for {
|
||||
return \*{shift()}
|
||||
}
|
||||
|
||||
sub _stash_for {
|
||||
return \%{ shift() . "::" };
|
||||
}
|
||||
}
|
||||
|
||||
use strict;
|
||||
use warnings qw( FATAL all );
|
||||
|
||||
use Carp ();
|
||||
use Scalar::Util qw(looks_like_number blessed);
|
||||
|
||||
|
||||
our %TYPES = (
|
||||
Bool => sub { !$_[0] || (defined $_[0] && looks_like_number($_[0]) && $_[0] == 1) },
|
||||
Num => sub { defined $_[0] && looks_like_number($_[0]) },
|
||||
Int => sub { defined $_[0] && looks_like_number($_[0]) && $_[0] == int($_[0]) },
|
||||
Str => sub { defined $_[0] },
|
||||
Object => sub { defined $_[0] && blessed($_[0]) },
|
||||
FileHandle => sub { local $@; require IO::Handle; fileno($_[0]) && $_[0]->opened },
|
||||
|
||||
map {
|
||||
my $type = /R/ ? $_ : uc $_;
|
||||
$_ . "Ref" => sub { ref $_[0] eq $type }
|
||||
} qw(Array Code Hash Regexp Glob Scalar)
|
||||
);
|
||||
|
||||
our %metadata_for;
|
||||
{
|
||||
package Mo::Object;
|
||||
|
||||
sub new {
|
||||
my $class = shift;
|
||||
my $args = $class->BUILDARGS(@_);
|
||||
|
||||
my @args_to_delete;
|
||||
while ( my ($attr, $meta) = each %{$metadata_for{$class}} ) {
|
||||
next unless exists $meta->{init_arg};
|
||||
my $init_arg = $meta->{init_arg};
|
||||
|
||||
if ( defined $init_arg ) {
|
||||
$args->{$attr} = delete $args->{$init_arg};
|
||||
}
|
||||
else {
|
||||
push @args_to_delete, $attr;
|
||||
}
|
||||
}
|
||||
|
||||
delete $args->{$_} for @args_to_delete;
|
||||
|
||||
for my $attribute ( keys %$args ) {
|
||||
if ( my $coerce = $metadata_for{$class}{$attribute}{coerce} ) {
|
||||
$args->{$attribute} = $coerce->($args->{$attribute});
|
||||
}
|
||||
if ( my $I = $metadata_for{$class}{$attribute}{isa} ) {
|
||||
( (my $I_name), $I ) = @{$I};
|
||||
Mo::_check_type_constaints($attribute, $I, $I_name, $args->{$attribute});
|
||||
}
|
||||
}
|
||||
|
||||
while ( my ($attribute, $meta) = each %{$metadata_for{$class}} ) {
|
||||
next unless $meta->{required};
|
||||
Carp::confess("Attribute ($attribute) is required for $class")
|
||||
if ! exists $args->{$attribute}
|
||||
}
|
||||
|
||||
@_ = %$args;
|
||||
my $self = bless $args, $class;
|
||||
|
||||
my @build_subs;
|
||||
my $linearized_isa = mro::get_linear_isa($class);
|
||||
|
||||
for my $isa_class ( @$linearized_isa ) {
|
||||
unshift @build_subs, *{ Mo::_glob_for "${isa_class}::BUILD" }{CODE};
|
||||
}
|
||||
exists &$_ && $_->( $self, @_ ) for grep { defined } @build_subs;
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub BUILDARGS {
|
||||
shift;
|
||||
my $ref;
|
||||
if ( @_ == 1 && ref($_[0]) ) {
|
||||
Carp::confess("Single parameters to new() must be a HASH ref")
|
||||
unless ref($_[0]) eq ref({});
|
||||
$ref = {%{$_[0]}} # We want a new reference, always
|
||||
}
|
||||
else {
|
||||
$ref = { @_ };
|
||||
}
|
||||
return $ref;
|
||||
}
|
||||
}
|
||||
|
||||
my %export_for;
|
||||
%Mo::Internal::Keyword = map { $_ => 1 } qw(has extends override);
|
||||
|
||||
sub Mo::import {
|
||||
warnings->import(qw(FATAL all));
|
||||
strict->import();
|
||||
|
||||
my $caller = scalar caller(); # Caller's package
|
||||
my $caller_pkg = $caller . "::"; # Caller's package with :: at the end
|
||||
my (%exports, %options);
|
||||
|
||||
my (undef, @features) = @_;
|
||||
my %ignore = ( map { $_ => 1 } qw( is isa init_arg builder buildargs clearer predicate build handles default required ) );
|
||||
for my $feature (grep { !$ignore{$_} } @features) {
|
||||
{ local $@; require "Mo/$feature.pm"; }
|
||||
{
|
||||
no strict 'refs';
|
||||
&{"Mo::${feature}::e"}(
|
||||
$caller_pkg,
|
||||
\%exports,
|
||||
\%options,
|
||||
\@_
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return if $exports{M};
|
||||
|
||||
%exports = (
|
||||
extends => sub {
|
||||
for my $class ( map { "$_" } @_ ) {
|
||||
$class =~ s{::|'}{/}g;
|
||||
{ local $@; eval { require "$class.pm" } } # or warn $@;
|
||||
}
|
||||
_set_package_isa($caller, @_);
|
||||
_set_inherited_metadata($caller);
|
||||
},
|
||||
override => \&override,
|
||||
has => sub {
|
||||
my $names = shift;
|
||||
for my $attribute ( ref $names ? @$names : $names ) {
|
||||
my %args = @_;
|
||||
my $method = ($args{is} || '') eq 'ro'
|
||||
? sub {
|
||||
Carp::confess("Cannot assign a value to a read-only accessor at reader ${caller_pkg}${attribute}")
|
||||
if $#_;
|
||||
return $_[0]{$attribute};
|
||||
}
|
||||
: sub {
|
||||
return $#_
|
||||
? $_[0]{$attribute} = $_[1]
|
||||
: $_[0]{$attribute};
|
||||
};
|
||||
|
||||
$metadata_for{$caller}{$attribute} = ();
|
||||
|
||||
if ( my $I = $args{isa} ) {
|
||||
my $orig_I = $I;
|
||||
my $type;
|
||||
if ( $I =~ /\A(ArrayRef|Maybe)\[(.*)\]\z/ ) {
|
||||
$I = _nested_constraints($attribute, $1, $2);
|
||||
}
|
||||
$metadata_for{$caller}{$attribute}{isa} = [$orig_I, $I];
|
||||
my $orig_method = $method;
|
||||
$method = sub {
|
||||
if ( $#_ ) {
|
||||
Mo::_check_type_constaints($attribute, $I, $orig_I, $_[1]);
|
||||
}
|
||||
goto &$orig_method;
|
||||
};
|
||||
}
|
||||
|
||||
if ( my $builder = $args{builder} ) {
|
||||
my $original_method = $method;
|
||||
$method = sub {
|
||||
$#_
|
||||
? goto &$original_method
|
||||
: ! exists $_[0]{$attribute}
|
||||
? $_[0]{$attribute} = $_[0]->$builder
|
||||
: goto &$original_method
|
||||
};
|
||||
}
|
||||
|
||||
if ( my $code = $args{default} ) {
|
||||
Carp::confess("${caller}::${attribute}'s default is $code, but should be a coderef")
|
||||
unless ref($code) eq 'CODE';
|
||||
my $original_method = $method;
|
||||
$method = sub {
|
||||
$#_
|
||||
? goto &$original_method
|
||||
: ! exists $_[0]{$attribute}
|
||||
? $_[0]{$attribute} = $_[0]->$code
|
||||
: goto &$original_method
|
||||
};
|
||||
}
|
||||
|
||||
if ( my $role = $args{does} ) {
|
||||
my $original_method = $method;
|
||||
$method = sub {
|
||||
if ( $#_ ) {
|
||||
Carp::confess(qq<Attribute ($attribute) doesn't consume a '$role' role">)
|
||||
unless Scalar::Util::blessed($_[1]) && eval { $_[1]->does($role) }
|
||||
}
|
||||
goto &$original_method
|
||||
};
|
||||
}
|
||||
|
||||
if ( my $coercion = $args{coerce} ) {
|
||||
$metadata_for{$caller}{$attribute}{coerce} = $coercion;
|
||||
my $original_method = $method;
|
||||
$method = sub {
|
||||
if ( $#_ ) {
|
||||
return $original_method->($_[0], $coercion->($_[1]))
|
||||
}
|
||||
goto &$original_method;
|
||||
}
|
||||
}
|
||||
|
||||
$method = $options{$_}->($method, $attribute, @_)
|
||||
for sort keys %options;
|
||||
|
||||
*{ _glob_for "${caller}::$attribute" } = $method;
|
||||
|
||||
if ( $args{required} ) {
|
||||
$metadata_for{$caller}{$attribute}{required} = 1;
|
||||
}
|
||||
|
||||
if ($args{clearer}) {
|
||||
*{ _glob_for "${caller}::$args{clearer}" }
|
||||
= sub { delete shift->{$attribute} }
|
||||
}
|
||||
|
||||
if ($args{predicate}) {
|
||||
*{ _glob_for "${caller}::$args{predicate}" }
|
||||
= sub { exists shift->{$attribute} }
|
||||
}
|
||||
|
||||
if ($args{handles}) {
|
||||
_has_handles($caller, $attribute, \%args);
|
||||
}
|
||||
|
||||
if (exists $args{init_arg}) {
|
||||
$metadata_for{$caller}{$attribute}{init_arg} = $args{init_arg};
|
||||
}
|
||||
}
|
||||
},
|
||||
%exports,
|
||||
);
|
||||
|
||||
$export_for{$caller} = [ keys %exports ];
|
||||
|
||||
for my $keyword ( keys %exports ) {
|
||||
*{ _glob_for "${caller}::$keyword" } = $exports{$keyword}
|
||||
}
|
||||
*{ _glob_for "${caller}::extends" }{CODE}->( "Mo::Object" )
|
||||
unless @{ *{ _glob_for "${caller}::ISA" }{ARRAY} || [] };
|
||||
};
|
||||
|
||||
sub _check_type_constaints {
|
||||
my ($attribute, $I, $I_name, $val) = @_;
|
||||
( ref($I) eq 'CODE'
|
||||
? $I->($val)
|
||||
: (ref $val eq $I
|
||||
|| ($val && $val eq $I)
|
||||
|| (exists $TYPES{$I} && $TYPES{$I}->($val)))
|
||||
)
|
||||
|| Carp::confess(
|
||||
qq<Attribute ($attribute) does not pass the type constraint because: >
|
||||
. qq<Validation failed for '$I_name' with value >
|
||||
. (defined $val ? Mo::Dumper($val) : 'undef') )
|
||||
}
|
||||
|
||||
sub _has_handles {
|
||||
my ($caller, $attribute, $args) = @_;
|
||||
my $handles = $args->{handles};
|
||||
|
||||
my $ref = ref $handles;
|
||||
my $kv;
|
||||
if ( $ref eq ref [] ) {
|
||||
$kv = { map { $_,$_ } @{$handles} };
|
||||
}
|
||||
elsif ( $ref eq ref {} ) {
|
||||
$kv = $handles;
|
||||
}
|
||||
elsif ( $ref eq ref qr// ) {
|
||||
Carp::confess("Cannot delegate methods based on a Regexp without a type constraint (isa)")
|
||||
unless $args->{isa};
|
||||
my $target_class = $args->{isa};
|
||||
$kv = {
|
||||
map { $_, $_ }
|
||||
grep { $_ =~ $handles }
|
||||
grep { !exists $Mo::Object::{$_} && $target_class->can($_) }
|
||||
grep { !$Mo::Internal::Keyword{$_} }
|
||||
keys %{ _stash_for $target_class }
|
||||
};
|
||||
}
|
||||
else {
|
||||
Carp::confess("handles for $ref not yet implemented");
|
||||
}
|
||||
|
||||
while ( my ($method, $target) = each %{$kv} ) {
|
||||
my $name = _glob_for "${caller}::$method";
|
||||
Carp::confess("You cannot overwrite a locally defined method ($method) with a delegation")
|
||||
if defined &$name;
|
||||
|
||||
my ($target, @curried_args) = ref($target) ? @$target : $target;
|
||||
*$name = sub {
|
||||
my $self = shift;
|
||||
my $delegate_to = $self->$attribute();
|
||||
my $error = "Cannot delegate $method to $target because the value of $attribute";
|
||||
Carp::confess("$error is not defined") unless $delegate_to;
|
||||
Carp::confess("$error is not an object (got '$delegate_to')")
|
||||
unless Scalar::Util::blessed($delegate_to) || (!ref($delegate_to) && $delegate_to->can($target));
|
||||
return $delegate_to->$target(@curried_args, @_);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub _nested_constraints {
|
||||
my ($attribute, $aggregate_type, $type) = @_;
|
||||
|
||||
my $inner_types;
|
||||
if ( $type =~ /\A(ArrayRef|Maybe)\[(.*)\]\z/ ) {
|
||||
$inner_types = _nested_constraints($1, $2);
|
||||
}
|
||||
else {
|
||||
$inner_types = $TYPES{$type};
|
||||
}
|
||||
|
||||
if ( $aggregate_type eq 'ArrayRef' ) {
|
||||
return sub {
|
||||
my ($val) = @_;
|
||||
return unless ref($val) eq ref([]);
|
||||
|
||||
if ($inner_types) {
|
||||
for my $value ( @{$val} ) {
|
||||
return unless $inner_types->($value)
|
||||
}
|
||||
}
|
||||
else {
|
||||
for my $value ( @{$val} ) {
|
||||
return unless $value && ($value eq $type
|
||||
|| (Scalar::Util::blessed($value) && $value->isa($type)));
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
};
|
||||
}
|
||||
elsif ( $aggregate_type eq 'Maybe' ) {
|
||||
return sub {
|
||||
my ($value) = @_;
|
||||
return 1 if ! defined($value);
|
||||
if ($inner_types) {
|
||||
return unless $inner_types->($value)
|
||||
}
|
||||
else {
|
||||
return unless $value eq $type
|
||||
|| (Scalar::Util::blessed($value) && $value->isa($type));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
Carp::confess("Nested aggregate types are only implemented for ArrayRefs and Maybe");
|
||||
}
|
||||
}
|
||||
|
||||
sub _set_package_isa {
|
||||
my ($package, @new_isa) = @_;
|
||||
|
||||
*{ _glob_for "${package}::ISA" } = [@new_isa];
|
||||
}
|
||||
|
||||
sub _set_inherited_metadata {
|
||||
my $class = shift;
|
||||
my $linearized_isa = mro::get_linear_isa($class);
|
||||
my %new_metadata;
|
||||
|
||||
for my $isa_class (reverse @$linearized_isa) {
|
||||
%new_metadata = (
|
||||
%new_metadata,
|
||||
%{ $metadata_for{$isa_class} || {} },
|
||||
);
|
||||
}
|
||||
$metadata_for{$class} = \%new_metadata;
|
||||
}
|
||||
|
||||
sub unimport {
|
||||
my $caller = scalar caller();
|
||||
my $stash = _stash_for( $caller );
|
||||
|
||||
delete $stash->{$_} for @{$export_for{$caller}};
|
||||
}
|
||||
|
||||
sub Dumper {
|
||||
require Data::Dumper;
|
||||
local $Data::Dumper::Indent = 0;
|
||||
local $Data::Dumper::Sortkeys = 0;
|
||||
local $Data::Dumper::Quotekeys = 0;
|
||||
local $Data::Dumper::Terse = 1;
|
||||
|
||||
Data::Dumper::Dumper(@_)
|
||||
}
|
||||
|
||||
BEGIN {
|
||||
if ($] >= 5.010) {
|
||||
{ local $@; require mro; }
|
||||
}
|
||||
else {
|
||||
local $@;
|
||||
eval {
|
||||
require MRO::Compat;
|
||||
} or do {
|
||||
*mro::get_linear_isa = *mro::get_linear_isa_dfs = sub {
|
||||
no strict 'refs';
|
||||
|
||||
my $classname = shift;
|
||||
|
||||
my @lin = ($classname);
|
||||
my %stored;
|
||||
foreach my $parent (@{"$classname\::ISA"}) {
|
||||
my $plin = mro::get_linear_isa_dfs($parent);
|
||||
foreach (@$plin) {
|
||||
next if exists $stored{$_};
|
||||
push(@lin, $_);
|
||||
$stored{$_} = 1;
|
||||
}
|
||||
}
|
||||
return \@lin;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub override {
|
||||
my ($methods, $code) = @_;
|
||||
my $caller = scalar caller;
|
||||
|
||||
for my $method ( ref($methods) ? @$methods : $methods ) {
|
||||
my $full_method = "${caller}::${method}";
|
||||
*{_glob_for $full_method} = $code;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
1;
|
||||
}
|
||||
# ###########################################################################
|
||||
# End Mo package
|
||||
# ###########################################################################
|
||||
|
||||
# ###########################################################################
|
||||
# DSNParser package
|
||||
# This package is a copy without comments from the original. The original
|
||||
@@ -1727,14 +2192,25 @@ sub parse_event {
|
||||
|
||||
if ( !$found_arg && $pos == $len ) {
|
||||
PTDEBUG && _d("Did not find arg, looking for special cases");
|
||||
local $INPUT_RECORD_SEPARATOR = ";\n";
|
||||
local $INPUT_RECORD_SEPARATOR = ";\n"; # get next line
|
||||
if ( defined(my $l = $next_event->()) ) {
|
||||
chomp $l;
|
||||
$l =~ s/^\s+//;
|
||||
PTDEBUG && _d("Found admin statement", $l);
|
||||
push @properties, 'cmd', 'Admin', 'arg', $l;
|
||||
push @properties, 'bytes', length($properties[-1]);
|
||||
$found_arg++;
|
||||
if ( $l =~ /^\s*[A-Z][a-z_]+: / ) {
|
||||
PTDEBUG && _d("Found NULL query before", $l);
|
||||
local $INPUT_RECORD_SEPARATOR = ";\n#";
|
||||
my $rest_of_event = $next_event->();
|
||||
push @{$self->{pending}}, $l . $rest_of_event;
|
||||
push @properties, 'cmd', 'Query', 'arg', '/* No query */';
|
||||
push @properties, 'bytes', 0;
|
||||
$found_arg++;
|
||||
}
|
||||
else {
|
||||
chomp $l;
|
||||
$l =~ s/^\s+//;
|
||||
PTDEBUG && _d("Found admin statement", $l);
|
||||
push @properties, 'cmd', 'Admin', 'arg', $l;
|
||||
push @properties, 'bytes', length($properties[-1]);
|
||||
$found_arg++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
PTDEBUG && _d("I can't figure out what to do with this line");
|
||||
@@ -1890,7 +2366,8 @@ sub parse_event {
|
||||
$cmd = $arg;
|
||||
}
|
||||
else {
|
||||
my ($user, undef, $db) = $arg =~ /(\S+)/g;
|
||||
my ($user) = $arg =~ m/(\S+)/;
|
||||
my ($db) = $arg =~ m/on (\S+)/;
|
||||
my $host;
|
||||
($user, $host) = split(/@/, $user);
|
||||
PTDEBUG && _d('Connect', $user, '@', $host, 'on', $db);
|
||||
@@ -2758,24 +3235,26 @@ use Time::Local qw(timegm timelocal);
|
||||
use Digest::MD5 qw(md5_hex);
|
||||
use B qw();
|
||||
|
||||
require Exporter;
|
||||
our @ISA = qw(Exporter);
|
||||
our %EXPORT_TAGS = ();
|
||||
our @EXPORT = ();
|
||||
our @EXPORT_OK = qw(
|
||||
micro_t
|
||||
percentage_of
|
||||
secs_to_time
|
||||
time_to_secs
|
||||
shorten
|
||||
ts
|
||||
parse_timestamp
|
||||
unix_timestamp
|
||||
any_unix_timestamp
|
||||
make_checksum
|
||||
crc32
|
||||
encode_json
|
||||
);
|
||||
BEGIN {
|
||||
require Exporter;
|
||||
our @ISA = qw(Exporter);
|
||||
our %EXPORT_TAGS = ();
|
||||
our @EXPORT = ();
|
||||
our @EXPORT_OK = qw(
|
||||
micro_t
|
||||
percentage_of
|
||||
secs_to_time
|
||||
time_to_secs
|
||||
shorten
|
||||
ts
|
||||
parse_timestamp
|
||||
unix_timestamp
|
||||
any_unix_timestamp
|
||||
make_checksum
|
||||
crc32
|
||||
encode_json
|
||||
);
|
||||
}
|
||||
|
||||
our $mysql_ts = qr/(\d\d)(\d\d)(\d\d) +(\d+):(\d+):(\d+)(\.\d+)?/;
|
||||
our $proper_ts = qr/(\d\d\d\d)-(\d\d)-(\d\d)[T ](\d\d):(\d\d):(\d\d)(\.\d+)?/;
|
||||
@@ -2907,6 +3386,9 @@ sub parse_timestamp {
|
||||
. (defined $f ? '%09.6f' : '%02d'),
|
||||
$y + 2000, $m, $d, $h, $i, (defined $f ? $s + $f : $s);
|
||||
}
|
||||
elsif ( $val =~ m/^$proper_ts$/ ) {
|
||||
return $val;
|
||||
}
|
||||
return $val;
|
||||
}
|
||||
|
||||
@@ -5706,8 +6188,7 @@ sub _d {
|
||||
{
|
||||
package ReportFormatter;
|
||||
|
||||
use strict;
|
||||
use warnings FATAL => 'all';
|
||||
use Mo;
|
||||
use English qw(-no_match_vars);
|
||||
use constant PTDEBUG => $ENV{PTDEBUG} || 0;
|
||||
|
||||
@@ -5717,40 +6198,102 @@ use POSIX qw(ceil);
|
||||
eval { require Term::ReadKey };
|
||||
my $have_term = $EVAL_ERROR ? 0 : 1;
|
||||
|
||||
sub new {
|
||||
my ( $class, %args ) = @_;
|
||||
my @required_args = qw();
|
||||
foreach my $arg ( @required_args ) {
|
||||
die "I need a $arg argument" unless $args{$arg};
|
||||
}
|
||||
my $self = {
|
||||
underline_header => 1,
|
||||
line_prefix => '# ',
|
||||
line_width => 78,
|
||||
column_spacing => ' ',
|
||||
extend_right => 0,
|
||||
truncate_line_mark => '...',
|
||||
column_errors => 'warn',
|
||||
truncate_header_side => 'left',
|
||||
strip_whitespace => 1,
|
||||
%args, # args above can be overriden, args below cannot
|
||||
n_cols => 0,
|
||||
};
|
||||
|
||||
if ( ($self->{line_width} || '') eq 'auto' ) {
|
||||
has underline_header => (
|
||||
is => 'ro',
|
||||
isa => 'Bool',
|
||||
default => sub { 1 },
|
||||
);
|
||||
has line_prefix => (
|
||||
is => 'ro',
|
||||
isa => 'Str',
|
||||
default => sub { '# ' },
|
||||
);
|
||||
has line_width => (
|
||||
is => 'ro',
|
||||
isa => 'Int',
|
||||
default => sub { 78 },
|
||||
);
|
||||
has column_spacing => (
|
||||
is => 'ro',
|
||||
isa => 'Str',
|
||||
default => sub { ' ' },
|
||||
);
|
||||
has extend_right => (
|
||||
is => 'ro',
|
||||
isa => 'Bool',
|
||||
default => sub { '' },
|
||||
);
|
||||
has truncate_line_mark => (
|
||||
is => 'ro',
|
||||
isa => 'Str',
|
||||
default => sub { '...' },
|
||||
);
|
||||
has column_errors => (
|
||||
is => 'ro',
|
||||
isa => 'Str',
|
||||
default => sub { 'warn' },
|
||||
);
|
||||
has truncate_header_side => (
|
||||
is => 'ro',
|
||||
isa => 'Str',
|
||||
default => sub { 'left' },
|
||||
);
|
||||
has strip_whitespace => (
|
||||
is => 'ro',
|
||||
isa => 'Bool',
|
||||
default => sub { 1 },
|
||||
);
|
||||
has title => (
|
||||
is => 'rw',
|
||||
isa => 'Str',
|
||||
predicate => 'has_title',
|
||||
);
|
||||
|
||||
|
||||
has n_cols => (
|
||||
is => 'rw',
|
||||
isa => 'Int',
|
||||
default => sub { 0 },
|
||||
init_arg => undef,
|
||||
);
|
||||
|
||||
has cols => (
|
||||
is => 'ro',
|
||||
isa => 'ArrayRef',
|
||||
init_arg => undef,
|
||||
default => sub { [] },
|
||||
clearer => 'clear_cols',
|
||||
);
|
||||
|
||||
has lines => (
|
||||
is => 'ro',
|
||||
isa => 'ArrayRef',
|
||||
init_arg => undef,
|
||||
default => sub { [] },
|
||||
clearer => 'clear_lines',
|
||||
);
|
||||
|
||||
has truncate_headers => (
|
||||
is => 'rw',
|
||||
isa => 'Bool',
|
||||
default => sub { undef },
|
||||
init_arg => undef,
|
||||
clearer => 'clear_truncate_headers',
|
||||
);
|
||||
|
||||
sub BUILDARGS {
|
||||
my $class = shift;
|
||||
my $args = $class->SUPER::BUILDARGS(@_);
|
||||
|
||||
if ( ($args->{line_width} || '') eq 'auto' ) {
|
||||
die "Cannot auto-detect line width because the Term::ReadKey module "
|
||||
. "is not installed" unless $have_term;
|
||||
($self->{line_width}) = GetTerminalSize();
|
||||
($args->{line_width}) = GetTerminalSize();
|
||||
PTDEBUG && _d('Line width:', $args->{line_width});
|
||||
}
|
||||
PTDEBUG && _d('Line width:', $self->{line_width});
|
||||
|
||||
return bless $self, $class;
|
||||
}
|
||||
|
||||
sub set_title {
|
||||
my ( $self, $title ) = @_;
|
||||
$self->{title} = $title;
|
||||
return;
|
||||
return $args;
|
||||
}
|
||||
|
||||
sub set_columns {
|
||||
@@ -5766,7 +6309,7 @@ sub set_columns {
|
||||
die "Column does not have a name" unless defined $col_name;
|
||||
|
||||
if ( $col->{width} ) {
|
||||
$col->{width_pct} = ceil(($col->{width} * 100) / $self->{line_width});
|
||||
$col->{width_pct} = ceil(($col->{width} * 100) / $self->line_width());
|
||||
PTDEBUG && _d('col:', $col_name, 'width:', $col->{width}, 'chars =',
|
||||
$col->{width_pct}, '%');
|
||||
}
|
||||
@@ -5793,10 +6336,10 @@ sub set_columns {
|
||||
|
||||
$col->{right_most} = 1 if $i == $#cols;
|
||||
|
||||
push @{$self->{cols}}, $col;
|
||||
push @{$self->cols}, $col;
|
||||
}
|
||||
|
||||
$self->{n_cols} = scalar @cols;
|
||||
$self->n_cols( scalar @cols );
|
||||
|
||||
if ( ($used_width || 0) > 100 ) {
|
||||
die "Total width_pct for all columns is >100%";
|
||||
@@ -5806,15 +6349,15 @@ sub set_columns {
|
||||
my $wid_per_col = int((100 - $used_width) / scalar @auto_width_cols);
|
||||
PTDEBUG && _d('Line width left:', (100-$used_width), '%;',
|
||||
'each auto width col:', $wid_per_col, '%');
|
||||
map { $self->{cols}->[$_]->{width_pct} = $wid_per_col } @auto_width_cols;
|
||||
map { $self->cols->[$_]->{width_pct} = $wid_per_col } @auto_width_cols;
|
||||
}
|
||||
|
||||
$min_hdr_wid += ($self->{n_cols} - 1) * length $self->{column_spacing};
|
||||
$min_hdr_wid += ($self->n_cols() - 1) * length $self->column_spacing();
|
||||
PTDEBUG && _d('min header width:', $min_hdr_wid);
|
||||
if ( $min_hdr_wid > $self->{line_width} ) {
|
||||
if ( $min_hdr_wid > $self->line_width() ) {
|
||||
PTDEBUG && _d('Will truncate headers because min header width',
|
||||
$min_hdr_wid, '> line width', $self->{line_width});
|
||||
$self->{truncate_headers} = 1;
|
||||
$min_hdr_wid, '> line width', $self->line_width());
|
||||
$self->truncate_headers(1);
|
||||
}
|
||||
|
||||
return;
|
||||
@@ -5823,14 +6366,14 @@ sub set_columns {
|
||||
sub add_line {
|
||||
my ( $self, @vals ) = @_;
|
||||
my $n_vals = scalar @vals;
|
||||
if ( $n_vals != $self->{n_cols} ) {
|
||||
if ( $n_vals != $self->n_cols() ) {
|
||||
$self->_column_error("Number of values $n_vals does not match "
|
||||
. "number of columns $self->{n_cols}");
|
||||
. "number of columns " . $self->n_cols());
|
||||
}
|
||||
for my $i ( 0..($n_vals-1) ) {
|
||||
my $col = $self->{cols}->[$i];
|
||||
my $col = $self->cols->[$i];
|
||||
my $val = defined $vals[$i] ? $vals[$i] : $col->{undef_value};
|
||||
if ( $self->{strip_whitespace} ) {
|
||||
if ( $self->strip_whitespace() ) {
|
||||
$val =~ s/^\s+//g;
|
||||
$val =~ s/\s+$//;
|
||||
$vals[$i] = $val;
|
||||
@@ -5839,7 +6382,7 @@ sub add_line {
|
||||
$col->{min_val} = min($width, ($col->{min_val} || $width));
|
||||
$col->{max_val} = max($width, ($col->{max_val} || $width));
|
||||
}
|
||||
push @{$self->{lines}}, \@vals;
|
||||
push @{$self->lines}, \@vals;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -5847,26 +6390,28 @@ sub get_report {
|
||||
my ( $self, %args ) = @_;
|
||||
|
||||
$self->_calculate_column_widths();
|
||||
$self->_truncate_headers() if $self->{truncate_headers};
|
||||
if ( $self->truncate_headers() ) {
|
||||
$self->_truncate_headers();
|
||||
}
|
||||
$self->_truncate_line_values(%args);
|
||||
|
||||
my @col_fmts = $self->_make_column_formats();
|
||||
my $fmt = ($self->{line_prefix} || '')
|
||||
. join($self->{column_spacing}, @col_fmts);
|
||||
my $fmt = $self->line_prefix()
|
||||
. join($self->column_spacing(), @col_fmts);
|
||||
PTDEBUG && _d('Format:', $fmt);
|
||||
|
||||
(my $hdr_fmt = $fmt) =~ s/%([^-])/%-$1/g;
|
||||
|
||||
my @lines;
|
||||
push @lines, sprintf "$self->{line_prefix}$self->{title}" if $self->{title};
|
||||
push @lines, $self->line_prefix() . $self->title() if $self->has_title();
|
||||
push @lines, $self->_truncate_line(
|
||||
sprintf($hdr_fmt, map { $_->{name} } @{$self->{cols}}),
|
||||
sprintf($hdr_fmt, map { $_->{name} } @{$self->cols}),
|
||||
strip => 1,
|
||||
mark => '',
|
||||
);
|
||||
|
||||
if ( $self->{underline_header} ) {
|
||||
my @underlines = map { '=' x $_->{print_width} } @{$self->{cols}};
|
||||
if ( $self->underline_header() ) {
|
||||
my @underlines = map { '=' x $_->{print_width} } @{$self->cols};
|
||||
push @lines, $self->_truncate_line(
|
||||
sprintf($fmt, map { $_ || '' } @underlines),
|
||||
mark => '',
|
||||
@@ -5877,19 +6422,23 @@ sub get_report {
|
||||
my $vals = $_;
|
||||
my $i = 0;
|
||||
my @vals = map {
|
||||
my $val = defined $_ ? $_ : $self->{cols}->[$i++]->{undef_value};
|
||||
my $val = defined $_ ? $_ : $self->cols->[$i++]->{undef_value};
|
||||
$val = '' if !defined $val;
|
||||
$val =~ s/\n/ /g;
|
||||
$val;
|
||||
} @$vals;
|
||||
my $line = sprintf($fmt, @vals);
|
||||
if ( $self->{extend_right} ) {
|
||||
if ( $self->extend_right() ) {
|
||||
$line;
|
||||
}
|
||||
else {
|
||||
$self->_truncate_line($line);
|
||||
}
|
||||
} @{$self->{lines}};
|
||||
} @{$self->lines};
|
||||
|
||||
$self->clear_cols();
|
||||
$self->clear_lines();
|
||||
$self->clear_truncate_headers();
|
||||
|
||||
return join("\n", @lines) . "\n";
|
||||
}
|
||||
@@ -5897,7 +6446,7 @@ sub get_report {
|
||||
sub truncate_value {
|
||||
my ( $self, $col, $val, $width, $side ) = @_;
|
||||
return $val if length $val <= $width;
|
||||
return $val if $col->{right_most} && $self->{extend_right};
|
||||
return $val if $col->{right_most} && $self->extend_right();
|
||||
$side ||= $col->{truncate_side};
|
||||
my $mark = $col->{truncate_mark};
|
||||
if ( $side eq 'right' ) {
|
||||
@@ -5917,8 +6466,8 @@ sub _calculate_column_widths {
|
||||
my ( $self ) = @_;
|
||||
|
||||
my $extra_space = 0;
|
||||
foreach my $col ( @{$self->{cols}} ) {
|
||||
my $print_width = int($self->{line_width} * ($col->{width_pct} / 100));
|
||||
foreach my $col ( @{$self->cols} ) {
|
||||
my $print_width = int($self->line_width() * ($col->{width_pct} / 100));
|
||||
|
||||
PTDEBUG && _d('col:', $col->{name}, 'width pct:', $col->{width_pct},
|
||||
'char width:', $print_width,
|
||||
@@ -5942,7 +6491,7 @@ sub _calculate_column_widths {
|
||||
|
||||
PTDEBUG && _d('Extra space:', $extra_space);
|
||||
while ( $extra_space-- ) {
|
||||
foreach my $col ( @{$self->{cols}} ) {
|
||||
foreach my $col ( @{$self->cols} ) {
|
||||
if ( $col->{auto_width}
|
||||
&& ( $col->{print_width} < $col->{max_val}
|
||||
|| $col->{print_width} < $col->{header_width})
|
||||
@@ -5957,8 +6506,8 @@ sub _calculate_column_widths {
|
||||
|
||||
sub _truncate_headers {
|
||||
my ( $self, $col ) = @_;
|
||||
my $side = $self->{truncate_header_side};
|
||||
foreach my $col ( @{$self->{cols}} ) {
|
||||
my $side = $self->truncate_header_side();
|
||||
foreach my $col ( @{$self->cols} ) {
|
||||
my $col_name = $col->{name};
|
||||
my $print_width = $col->{print_width};
|
||||
next if length $col_name <= $print_width;
|
||||
@@ -5971,10 +6520,10 @@ sub _truncate_headers {
|
||||
|
||||
sub _truncate_line_values {
|
||||
my ( $self, %args ) = @_;
|
||||
my $n_vals = $self->{n_cols} - 1;
|
||||
foreach my $vals ( @{$self->{lines}} ) {
|
||||
my $n_vals = $self->n_cols() - 1;
|
||||
foreach my $vals ( @{$self->lines} ) {
|
||||
for my $i ( 0..$n_vals ) {
|
||||
my $col = $self->{cols}->[$i];
|
||||
my $col = $self->cols->[$i];
|
||||
my $val = defined $vals->[$i] ? $vals->[$i] : $col->{undef_value};
|
||||
my $width = length $val;
|
||||
|
||||
@@ -6000,9 +6549,9 @@ sub _truncate_line_values {
|
||||
sub _make_column_formats {
|
||||
my ( $self ) = @_;
|
||||
my @col_fmts;
|
||||
my $n_cols = $self->{n_cols} - 1;
|
||||
my $n_cols = $self->n_cols() - 1;
|
||||
for my $i ( 0..$n_cols ) {
|
||||
my $col = $self->{cols}->[$i];
|
||||
my $col = $self->cols->[$i];
|
||||
|
||||
my $width = $col->{right_most} && !$col->{right_justify} ? ''
|
||||
: $col->{print_width};
|
||||
@@ -6015,12 +6564,12 @@ sub _make_column_formats {
|
||||
|
||||
sub _truncate_line {
|
||||
my ( $self, $line, %args ) = @_;
|
||||
my $mark = defined $args{mark} ? $args{mark} : $self->{truncate_line_mark};
|
||||
my $mark = defined $args{mark} ? $args{mark} : $self->truncate_line_mark();
|
||||
if ( $line ) {
|
||||
$line =~ s/\s+$// if $args{strip};
|
||||
my $len = length($line);
|
||||
if ( $len > $self->{line_width} ) {
|
||||
$line = substr($line, 0, $self->{line_width} - length $mark);
|
||||
if ( $len > $self->line_width() ) {
|
||||
$line = substr($line, 0, $self->line_width() - length $mark);
|
||||
$line .= $mark if $mark;
|
||||
}
|
||||
}
|
||||
@@ -6030,7 +6579,7 @@ sub _truncate_line {
|
||||
sub _column_error {
|
||||
my ( $self, $err ) = @_;
|
||||
my $msg = "Column error: $err";
|
||||
$self->{column_errors} eq 'die' ? die $msg : warn $msg;
|
||||
$self->column_errors() eq 'die' ? die $msg : warn $msg;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -7835,7 +8384,7 @@ sub main {
|
||||
long_last_column => 1,
|
||||
extend_right => 1,
|
||||
);
|
||||
$profile->set_title("Profile");
|
||||
$profile->title("Profile");
|
||||
$profile->set_columns(
|
||||
{ name => 'Query ID', },
|
||||
{ name => 'NOTE', right_justify => 1, },
|
||||
@@ -8694,8 +9243,7 @@ L<http://www.percona.com/software/> for more software developed by Percona.
|
||||
|
||||
=head1 COPYRIGHT, LICENSE, AND WARRANTY
|
||||
|
||||
This program is copyright 2010-2012 Percona Inc.
|
||||
Feedback and improvements are welcome.
|
||||
This program is copyright 2010-2013 Percona Ireland Ltd.
|
||||
|
||||
THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
@@ -8713,6 +9261,6 @@ Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
pt-query-advisor 2.1.7
|
||||
pt-query-advisor 2.1.8
|
||||
|
||||
=cut
|
||||
|
@@ -64,7 +64,7 @@ BEGIN {
|
||||
# ###########################################################################
|
||||
{
|
||||
package Percona::Toolkit;
|
||||
our $VERSION = '2.1.7';
|
||||
our $VERSION = '2.1.8';
|
||||
|
||||
1;
|
||||
}
|
||||
@@ -7977,14 +7977,14 @@ sub _d {
|
||||
{
|
||||
package JSONReportFormatter;
|
||||
use Mo;
|
||||
use JSON ();
|
||||
|
||||
use List::Util qw(sum);
|
||||
|
||||
use List::Util qw(sum);
|
||||
use Transformers qw(make_checksum parse_timestamp);
|
||||
|
||||
use constant PTDEBUG => $ENV{PTDEBUG} || 0;
|
||||
|
||||
my $have_json = eval { require JSON };
|
||||
|
||||
our $pretty_json = undef;
|
||||
our $sorted_json = undef;
|
||||
|
||||
@@ -7994,11 +7994,23 @@ has _json => (
|
||||
is => 'ro',
|
||||
init_arg => undef,
|
||||
builder => '_build_json',
|
||||
handles => { encode_json => 'encode' },
|
||||
);
|
||||
|
||||
sub _build_json {
|
||||
return JSON->new->utf8->pretty($pretty_json)->canonical($sorted_json);
|
||||
return unless $have_json;
|
||||
return JSON->new->utf8
|
||||
->pretty($pretty_json)
|
||||
->canonical($sorted_json);
|
||||
}
|
||||
|
||||
sub encode_json {
|
||||
my ($self, $encode) = @_;
|
||||
if ( my $json = $self->_json ) {
|
||||
return $json->encode($encode);
|
||||
}
|
||||
else {
|
||||
return Transformers::encode_json($encode);
|
||||
}
|
||||
}
|
||||
|
||||
override [qw(rusage date hostname files header profile prepared)] => sub {
|
||||
@@ -8076,7 +8088,9 @@ override query_report => sub {
|
||||
};
|
||||
}
|
||||
|
||||
return $self->encode_json(\@queries) . "\n";
|
||||
my $json = $self->encode_json(\@queries);
|
||||
$json .= "\n" if $json !~ /\n\Z/;
|
||||
return $json . "\n";
|
||||
};
|
||||
|
||||
1;
|
||||
@@ -15284,7 +15298,8 @@ Analyze, aggregate, and report on a slow query log:
|
||||
Review a slow log, saving results to the test.query_review table in a MySQL
|
||||
server running on host1. See L<"--review"> for more on reviewing queries:
|
||||
|
||||
pt-query-digest --review h=host1,D=test,t=query_review /path/to/slow.log
|
||||
pt-query-digest --review h=host1 --review-table test.query_review
|
||||
--history-table test.query_history /path/to/slow.log
|
||||
|
||||
Print the structure of events so you can construct a complex L<"--filter">:
|
||||
|
||||
@@ -15314,7 +15329,7 @@ is safe to run even on production systems, but you might want to monitor it
|
||||
until you are satisfied that the input you give it does not cause undue load.
|
||||
|
||||
Various options will cause pt-query-digest to insert data into tables, execute
|
||||
SQL queries, and so on. These include the L<"--review"> options.
|
||||
SQL queries, and so on. These include the L<"--review"> option.
|
||||
|
||||
At the time of this release, we know of no bugs that could cause serious harm
|
||||
to users.
|
||||
@@ -15795,7 +15810,9 @@ Continue parsing even if there is an error. The tool will not continue
|
||||
forever: it stops once any process causes 100 errors, in which case there
|
||||
is probably a bug in the tool or the input is invalid.
|
||||
|
||||
=item --create-review-tables
|
||||
=item --[no]create-review-tables
|
||||
|
||||
default: yes
|
||||
|
||||
Create the L<"--review"> tables if they do not exist.
|
||||
|
||||
@@ -16305,10 +16322,15 @@ type: DSN
|
||||
Store a sample of each class of query in this DSN, plus historical values
|
||||
for review trend analysis
|
||||
|
||||
The argument specifies a table to store all unique query fingerprints in. The
|
||||
table must have at least the following columns. You can add more columns for
|
||||
your own special purposes, but they won't be used by pt-query-digest. The
|
||||
following CREATE TABLE definition is also used for L<"--create-review-table">.
|
||||
The argument specifies a host to store all unique query fingerprints in; the
|
||||
databases and tables were this data is stored can be specified with the
|
||||
L<"--review-table"> and L<"--history-table"> options.
|
||||
By default, if the table doesn't exist the tool mtries creating it; This
|
||||
behavior can bhe controlled with the L<"--[no]create-review-tables"> option.
|
||||
If the table was created manually, it must have at least the following columns.
|
||||
You can add more columns for your own special purposes, but they won't be used
|
||||
by pt-query-digest. The following CREATE TABLE definition is also used by
|
||||
L<"--no-create-review-tables">.
|
||||
|
||||
=for comment ignore-pt-internal-value
|
||||
MAGIC_create_review:
|
||||
@@ -16346,7 +16368,7 @@ fingerprint. This option depends on C<--group-by fingerprint> (which is the
|
||||
default). It will not work otherwise.
|
||||
|
||||
|
||||
Additionally, pt-query-digest will save information into a review table,
|
||||
Additionally, pt-query-digest will save historical information into a review table,
|
||||
so you can see how classes of queries have changed over time. You can
|
||||
change the destination table with the L<"--history-table">
|
||||
|
||||
@@ -16379,7 +16401,7 @@ you could also just add a ts_min column and make it a DATE type, so you'd get
|
||||
one row per class of queries per day.
|
||||
|
||||
The default table structure follows. The following table definition is used
|
||||
for L<"--create-review-tables">:
|
||||
for L<"--[no]create-review-tables">:
|
||||
|
||||
=for comment ignore-pt-internal-value
|
||||
MAGIC_create_review_history
|
||||
@@ -17297,8 +17319,7 @@ L<http://www.percona.com/software/> for more software developed by Percona.
|
||||
|
||||
=head1 COPYRIGHT, LICENSE, AND WARRANTY
|
||||
|
||||
This program is copyright 2008-2012 Percona Inc.
|
||||
Feedback and improvements are welcome.
|
||||
This program is copyright 2008-2013 Percona Ireland Ltd.
|
||||
|
||||
THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
@@ -17316,6 +17337,6 @@ Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
pt-query-digest 2.1.7
|
||||
pt-query-digest 2.1.8
|
||||
|
||||
=cut
|
||||
|
@@ -2285,8 +2285,8 @@ L<http://www.percona.com/software/> for more software developed by Percona.
|
||||
|
||||
=head1 COPYRIGHT, LICENSE, AND WARRANTY
|
||||
|
||||
This program is copyright 2007-2011 Baron Schwartz, 2011-2012 Percona Inc.
|
||||
Feedback and improvements are welcome.
|
||||
This program is copyright 2011-2013 Percona Ireland Ltd,
|
||||
2007-2011 Baron Schwartz.
|
||||
|
||||
THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
@@ -2304,6 +2304,6 @@ Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
pt-show-grants 2.1.7
|
||||
pt-show-grants 2.1.8
|
||||
|
||||
=cut
|
||||
|
@@ -762,8 +762,8 @@ L<http://www.percona.com/software/> for more software developed by Percona.
|
||||
|
||||
=head1 COPYRIGHT, LICENSE, AND WARRANTY
|
||||
|
||||
This program is copyright 2010-2011 Baron Schwartz, 2011-2012 Percona Inc.
|
||||
Feedback and improvements are welcome.
|
||||
This program is copyright 2011-2013 Percona Ireland Ltd,
|
||||
2010-2011 Baron Schwartz.
|
||||
|
||||
THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
@@ -781,7 +781,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
pt-sift 2.1.7
|
||||
pt-sift 2.1.8
|
||||
|
||||
=cut
|
||||
|
||||
|
@@ -36,7 +36,7 @@ BEGIN {
|
||||
# ###########################################################################
|
||||
{
|
||||
package Percona::Toolkit;
|
||||
our $VERSION = '2.1.7';
|
||||
our $VERSION = '2.1.8';
|
||||
|
||||
1;
|
||||
}
|
||||
@@ -2268,6 +2268,9 @@ sub parse_timestamp {
|
||||
. (defined $f ? '%09.6f' : '%02d'),
|
||||
$y + 2000, $m, $d, $h, $i, (defined $f ? $s + $f : $s);
|
||||
}
|
||||
elsif ( $val =~ m/^$proper_ts$/ ) {
|
||||
return $val;
|
||||
}
|
||||
return $val;
|
||||
}
|
||||
|
||||
@@ -4578,9 +4581,8 @@ L<http://www.percona.com/software/> for more software developed by Percona.
|
||||
|
||||
=head1 COPYRIGHT, LICENSE, AND WARRANTY
|
||||
|
||||
This program is copyright 2007-2011 Sergey Zhuravle and Baron Schwartz,
|
||||
2011-2012 Percona Inc.
|
||||
Feedback and improvements are welcome.
|
||||
This program is copyright 2011-2013 Percona Ireland Ltd,
|
||||
2007-2011 Sergey Zhuravle and Baron Schwartz.
|
||||
|
||||
THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
@@ -4598,6 +4600,6 @@ Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
pt-slave-delay 2.1.7
|
||||
pt-slave-delay 2.1.8
|
||||
|
||||
=cut
|
||||
|
@@ -3175,6 +3175,9 @@ sub parse_timestamp {
|
||||
. (defined $f ? '%09.6f' : '%02d'),
|
||||
$y + 2000, $m, $d, $h, $i, (defined $f ? $s + $f : $s);
|
||||
}
|
||||
elsif ( $val =~ m/^$proper_ts$/ ) {
|
||||
return $val;
|
||||
}
|
||||
return $val;
|
||||
}
|
||||
|
||||
@@ -4003,8 +4006,8 @@ L<http://www.percona.com/software/> for more software developed by Percona.
|
||||
|
||||
=head1 COPYRIGHT, LICENSE, AND WARRANTY
|
||||
|
||||
This program is copyright 2007-2011 Baron Schwartz, 2011-2012 Percona Inc.
|
||||
Feedback and improvements are welcome.
|
||||
This program is copyright 2011-2013 Percona Ireland Ltd,
|
||||
2007-2011 Baron Schwartz.
|
||||
|
||||
THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
@@ -4022,6 +4025,6 @@ Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
pt-slave-find 2.1.7
|
||||
pt-slave-find 2.1.8
|
||||
|
||||
=cut
|
||||
|
@@ -37,7 +37,7 @@ BEGIN {
|
||||
# ###########################################################################
|
||||
{
|
||||
package Percona::Toolkit;
|
||||
our $VERSION = '2.1.7';
|
||||
our $VERSION = '2.1.8';
|
||||
|
||||
1;
|
||||
}
|
||||
@@ -5500,8 +5500,8 @@ L<http://www.percona.com/software/> for more software developed by Percona.
|
||||
|
||||
=head1 COPYRIGHT, LICENSE, AND WARRANTY
|
||||
|
||||
This program is copyright 2007-2011 Baron Schwartz, 2011-2012 Percona Inc.
|
||||
Feedback and improvements are welcome.
|
||||
This program is copyright 2011-2013 Percona Ireland Ltd,
|
||||
2007-2011 Baron Schwartz.
|
||||
|
||||
THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
@@ -5519,6 +5519,6 @@ Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
pt-slave-restart 2.1.7
|
||||
pt-slave-restart 2.1.8
|
||||
|
||||
=cut
|
||||
|
@@ -71,7 +71,7 @@ PO_DIR="" # Directory with program option spec files
|
||||
usage() {
|
||||
local file="$1"
|
||||
|
||||
local usage=$(grep '^Usage: ' "$file")
|
||||
local usage="$(grep '^Usage: ' "$file")"
|
||||
echo $usage
|
||||
echo
|
||||
echo "For more information, 'man $TOOL' or 'perldoc $file'."
|
||||
@@ -1965,8 +1965,8 @@ L<http://www.percona.com/software/> for more software developed by Percona.
|
||||
|
||||
=head1 COPYRIGHT, LICENSE, AND WARRANTY
|
||||
|
||||
This program is copyright 2010-2011 Baron Schwartz, 2011-2012 Percona Inc.
|
||||
Feedback and improvements are welcome.
|
||||
This program is copyright 2011-2013 Percona Ireland Ltd,
|
||||
2010-2011 Baron Schwartz.
|
||||
|
||||
THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
@@ -1984,7 +1984,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
pt-stalk 2.1.7
|
||||
pt-stalk 2.1.8
|
||||
|
||||
=cut
|
||||
|
||||
|
@@ -78,7 +78,7 @@ PO_DIR="" # Directory with program option spec files
|
||||
usage() {
|
||||
local file="$1"
|
||||
|
||||
local usage=$(grep '^Usage: ' "$file")
|
||||
local usage="$(grep '^Usage: ' "$file")"
|
||||
echo $usage
|
||||
echo
|
||||
echo "For more information, 'man $TOOL' or 'perldoc $file'."
|
||||
@@ -2654,8 +2654,8 @@ L<http://www.percona.com/software/> for more software developed by Percona.
|
||||
|
||||
=head1 COPYRIGHT, LICENSE, AND WARRANTY
|
||||
|
||||
This program is copyright 2010-2011 Baron Schwartz, 2011-2012 Percona Inc.
|
||||
Feedback and improvements are welcome.
|
||||
This program is copyright 2011-2013 Percona Ireland Ltd,
|
||||
2010-2011 Baron Schwartz.
|
||||
|
||||
THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
@@ -2673,7 +2673,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
pt-summary 2.1.7
|
||||
pt-summary 2.1.8
|
||||
|
||||
=cut
|
||||
|
||||
|
@@ -53,7 +53,7 @@ BEGIN {
|
||||
# ###########################################################################
|
||||
{
|
||||
package Percona::Toolkit;
|
||||
our $VERSION = '2.1.7';
|
||||
our $VERSION = '2.1.8';
|
||||
|
||||
1;
|
||||
}
|
||||
@@ -7360,6 +7360,9 @@ sub parse_timestamp {
|
||||
. (defined $f ? '%09.6f' : '%02d'),
|
||||
$y + 2000, $m, $d, $h, $i, (defined $f ? $s + $f : $s);
|
||||
}
|
||||
elsif ( $val =~ m/^$proper_ts$/ ) {
|
||||
return $val;
|
||||
}
|
||||
return $val;
|
||||
}
|
||||
|
||||
@@ -8741,6 +8744,15 @@ sub main {
|
||||
} @$slaves;
|
||||
}
|
||||
PTDEBUG && _d(scalar @$slaves, 'slaves found');
|
||||
if ( !@$slaves && $o->get('recursion-method')->[0] ne 'none' ) {
|
||||
$exit_status |= 1;
|
||||
if ( $o->get('quiet') < 2 ) {
|
||||
warn "Diffs cannot be detected because no slaves were found. "
|
||||
. "Please read the --recursion-method documentation for "
|
||||
. "information.\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# https://bugs.launchpad.net/percona-toolkit/+bug/938068
|
||||
if ( $o->get('check-binlog-format') ) {
|
||||
@@ -11490,6 +11502,13 @@ type: array; default: processlist,hosts
|
||||
|
||||
Preferred recursion method for discovering replicas. pt-table-checksum
|
||||
performs several L<"REPLICA CHECKS"> before and while running.
|
||||
|
||||
Although replicas are not required to run pt-table-checksum, the tool
|
||||
cannot detect diffs on slaves that it cannot discover. Therefore,
|
||||
a warning is printed and the L<"EXIT STATUS"> is non-zero if no replicas
|
||||
are found and the method is not C<none>. If this happens, try a different
|
||||
recursion method, or use the C<dsn> method to specify the replicas to check.
|
||||
|
||||
Possible methods are:
|
||||
|
||||
METHOD USES
|
||||
@@ -11935,8 +11954,8 @@ L<http://www.percona.com/software/> for more software developed by Percona.
|
||||
|
||||
=head1 COPYRIGHT, LICENSE, AND WARRANTY
|
||||
|
||||
This program is copyright 2007-2011 Baron Schwartz, 2011-2012 Percona Inc.
|
||||
Feedback and improvements are welcome.
|
||||
This program is copyright 2011-2013 Percona Ireland Ltd,
|
||||
2007-2011 Baron Schwartz.
|
||||
|
||||
THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
@@ -11954,6 +11973,6 @@ Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
pt-table-checksum 2.1.7
|
||||
pt-table-checksum 2.1.8
|
||||
|
||||
=cut
|
||||
|
@@ -52,7 +52,7 @@ BEGIN {
|
||||
# ###########################################################################
|
||||
{
|
||||
package Percona::Toolkit;
|
||||
our $VERSION = '2.1.7';
|
||||
our $VERSION = '2.1.8';
|
||||
|
||||
1;
|
||||
}
|
||||
@@ -8036,6 +8036,9 @@ sub parse_timestamp {
|
||||
. (defined $f ? '%09.6f' : '%02d'),
|
||||
$y + 2000, $m, $d, $h, $i, (defined $f ? $s + $f : $s);
|
||||
}
|
||||
elsif ( $val =~ m/^$proper_ts$/ ) {
|
||||
return $val;
|
||||
}
|
||||
return $val;
|
||||
}
|
||||
|
||||
@@ -12614,8 +12617,8 @@ L<http://www.percona.com/software/> for more software developed by Percona.
|
||||
|
||||
=head1 COPYRIGHT, LICENSE, AND WARRANTY
|
||||
|
||||
This program is copyright 2007-2011 Baron Schwartz, 2011-2012 Percona Inc.
|
||||
Feedback and improvements are welcome.
|
||||
This program is copyright 2011-2013 Percona Ireland Ltd,
|
||||
2007-2011 Baron Schwartz.
|
||||
|
||||
THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
@@ -12633,6 +12636,6 @@ Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
pt-table-sync 2.1.7
|
||||
pt-table-sync 2.1.8
|
||||
|
||||
=cut
|
||||
|
@@ -7364,8 +7364,7 @@ L<http://www.percona.com/software/> for more software developed by Percona.
|
||||
|
||||
=head1 COPYRIGHT, LICENSE, AND WARRANTY
|
||||
|
||||
This program is copyright 2012 Percona Inc.
|
||||
Feedback and improvements are welcome.
|
||||
This program is copyright 2012-2013 Percona Ireland Ltd.
|
||||
|
||||
THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
@@ -7383,6 +7382,6 @@ Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
pt-table-usage 2.1.7
|
||||
pt-table-usage 2.1.8
|
||||
|
||||
=cut
|
||||
|
818
bin/pt-upgrade
818
bin/pt-upgrade
File diff suppressed because it is too large
Load Diff
@@ -40,7 +40,7 @@ BEGIN {
|
||||
# ###########################################################################
|
||||
{
|
||||
package Percona::Toolkit;
|
||||
our $VERSION = '2.1.7';
|
||||
our $VERSION = '2.1.8';
|
||||
|
||||
1;
|
||||
}
|
||||
@@ -5851,8 +5851,7 @@ L<http://www.percona.com/software/> for more software developed by Percona.
|
||||
|
||||
=head1 COPYRIGHT, LICENSE, AND WARRANTY
|
||||
|
||||
This program is copyright 2010-2012 Percona Inc.
|
||||
Feedback and improvements are welcome.
|
||||
This program is copyright 2010-2013 Percona Ireland Ltd.
|
||||
|
||||
THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
@@ -5870,6 +5869,6 @@ Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
pt-variable-advisor 2.1.7
|
||||
pt-variable-advisor 2.1.8
|
||||
|
||||
=cut
|
||||
|
@@ -3124,8 +3124,8 @@ L<http://www.percona.com/software/> for more software developed by Percona.
|
||||
|
||||
=head1 COPYRIGHT, LICENSE, AND WARRANTY
|
||||
|
||||
This program is copyright 2007-2011 Baron Schwartz, 2011-2012 Percona Inc.
|
||||
Feedback and improvements are welcome.
|
||||
This program is copyright 2011-2013 Percona Ireland Ltd,
|
||||
2007-2011 Baron Schwartz.
|
||||
|
||||
THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
@@ -3143,6 +3143,6 @@ Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
pt-visual-explain 2.1.7
|
||||
pt-visual-explain 2.1.8
|
||||
|
||||
=cut
|
||||
|
@@ -1,3 +1,41 @@
|
||||
percona-toolkit (2.1.8) unstable; urgency=low
|
||||
|
||||
* Beta support for MySQL 5.6
|
||||
* Beta support for Percona XtraDB Cluster
|
||||
* pt-online-schema-change: If ran on Percona XtraDB Cluster, requires PXC 5.5.28 or newer
|
||||
* pt-table-checksum: If ran on Percona XtraDB Cluster, requires PXC 5.5.28 or newer
|
||||
* pt-upgrade: Added --[no]disable-query-cache
|
||||
* Fixed bug 927955: Bad pod2rst transformation
|
||||
* Fixed bug 898665: Bad online docs formatting for --[no]vars
|
||||
* Fixed bug 1022622: pt-config-diff is case-sensitive
|
||||
* Fixed bug 1007938: pt-config-diff doesn't handle end-of-line comments
|
||||
* Fixed bug 917770: pt-config-diff Use of uninitialized value in substitution (s///) at line 1996
|
||||
* Fixed bug 1082104: pt-deadlock-logger doesn't handle usernames with dashes
|
||||
* Fixed bug 886059: pt-heartbeat handles timezones inconsistently
|
||||
* Fixed bug 1086259: pt-kill --log-dsn timestamp is wrong
|
||||
* Fixed bug 1015590: pt-mysql-summary doesn't handle renamed variables in Percona Server 5.5
|
||||
* Fixed bug 1079341: pt-online-schema-change checks for foreign keys on MyISAM tables
|
||||
* Fixed bug 823431: pt-query-advisor hangs on big queries
|
||||
* Fixed bug 996069: pt-query-advisor RES.001 is incorrect
|
||||
* Fixed bug 933465: pt-query-advisor false positive on RES.001
|
||||
* Fixed bug 937234: pt-query-advisor issues wrong RES.001
|
||||
* Fixed bug 1082599: pt-query-digest fails to parse timestamp with no query
|
||||
* Fixed bug 1078838: pt-query-digest doesn't parse general log with "Connect user as user"
|
||||
* Fixed bug 957442: pt-query-digest with custom --group-by throws error
|
||||
* Fixed bug 887638: pt-query-digest prints negative byte offset
|
||||
* Fixed bug 831525: pt-query-digest help output mangled
|
||||
* Fixed bug 932614: pt-slave-restart CHANGE MASTER query causes error
|
||||
* Fixed bug 1046440: pt-stalk purge_samples slows down checks
|
||||
* Fixed bug 986847: pt-stalk does not report NFS iostat
|
||||
* Fixed bug 1074179: pt-table-checksum doesn't ignore tables for --replicate-check-only
|
||||
* Fixed bug 911385: pt-table-checksum v2 fails when --resume + --ignore-database is used
|
||||
* Fixed bug 1041391: pt-table-checksum debug statement for "Chosen hash func" prints undef
|
||||
* Fixed bug 1075638: pt-table-checksum Illegal division by zero at line 7950
|
||||
* Fixed bug 1052475: pt-table-checksum uninitialized value in numeric lt (<) at line 8611
|
||||
* Fixed bug 1078887: Tools let --set-vars clobber the required SQL mode
|
||||
|
||||
-- Percona Toolkit Developers <toolkit-dev@percona.com> Fri, 21 Dec 2012 17:31:09 +0000
|
||||
|
||||
percona-toolkit (2.1.7) unstable; urgency=low
|
||||
|
||||
* Fixed bug 1080384: pt-table-checksum 2.1.6 crashes using PTDEBUG
|
||||
|
@@ -50,7 +50,7 @@ copyright = u'2011, Percona Inc'
|
||||
# The short X.Y version.
|
||||
version = '2.1'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '2.1.7'
|
||||
release = '2.1.8'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
|
@@ -17,7 +17,7 @@ no libraries are installed.
|
||||
|
||||
Percona Toolkit is derived from Maatkit and Aspersa, two of the best-known
|
||||
toolkits for MySQL server administration. It is developed and supported by
|
||||
Percona Inc. For more information and other free, open-source software
|
||||
Percona. For more information and other free, open-source software
|
||||
developed by Percona, visit L<http://www.percona.com/software/>.
|
||||
|
||||
=head1 TOOLS
|
||||
@@ -485,13 +485,33 @@ see L<"ENVIRONMENT">.
|
||||
|
||||
=head1 AUTHORS
|
||||
|
||||
Percona Toolkit is primarily developed by Baron Schwartz and Daniel Nichter,
|
||||
both of whom are employed by Percona Inc. See each program's documentation
|
||||
for details.
|
||||
=over
|
||||
|
||||
=item Baron Schwartz
|
||||
|
||||
Baron created Maatkit, from which Percona Toolkit was forked. Many of
|
||||
the tools and modules were originally written by Baron.
|
||||
|
||||
=item Daniel Nichter
|
||||
|
||||
Daniel began helping Baron with Maatkit and, later, Percona Toolkit in
|
||||
June, 2008. He is the project's lead developer, employed by Percona.
|
||||
|
||||
=item Brian Fraser
|
||||
|
||||
Brian started with Percona in December, 2011. He works on Percona Toolkit
|
||||
full-time, employed by Percona.
|
||||
|
||||
=item Others
|
||||
|
||||
Many people have contributed code over the years. See each tool's
|
||||
"AUTHORS" section for details.
|
||||
|
||||
=back
|
||||
|
||||
=head1 COPYRIGHT, LICENSE, AND WARRANTY
|
||||
|
||||
Percona Toolkit is copyright 2011-2012 Percona Inc. and others.
|
||||
Percona Toolkit is copyright 2011-2013 Percona Ireland Ltd and others.
|
||||
See each program's documentation for complete copyright notices.
|
||||
|
||||
THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
@@ -510,6 +530,6 @@ Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
Percona Toolkit v2.1.7 released 2012-11-19
|
||||
Percona Toolkit v2.1.8 released 2012-12-21
|
||||
|
||||
=cut
|
||||
|
@@ -1,6 +1,89 @@
|
||||
Release Notes
|
||||
*************
|
||||
|
||||
v2.1.8 released 2012-12-21
|
||||
==========================
|
||||
|
||||
Percona Toolkit 2.1.8 has been released. This release includes 28 bug fixes, beta support for MySQL 5.6, and extensive support for Percona XtraDB Cluster (PXC). Users intending on running the tools on Percona XtraDB Cluster or MySQL 5.6 should upgrade. The following tools have been verified to work on PXC versions 5.5.28 and newer:
|
||||
|
||||
* pt-table-chcecksum
|
||||
* pt-online-schema-change
|
||||
* pt-archive
|
||||
* pt-mysql-summary
|
||||
* pt-heartbeat
|
||||
* pt-variable-advisor
|
||||
* pt-config-diff
|
||||
* pt-deadlock-logger
|
||||
|
||||
However, there are limitations when running these tools on PXC; see the Percona XtraDB Cluster section in each tool's documentation for further details. All other tools, with the exception of pt-slave-find, pt-slave-delay and pt-slave-restart, should also work correctly, but in some cases they have not been modified to take advantage of PXC features, so they may behave differently in future releases.
|
||||
|
||||
The bug fixes are widely assorted. The following highlights some of the more interesting and "hot" bugs:
|
||||
|
||||
* Fixed bug 1082599: pt-query-digest fails to parse timestamp with no query
|
||||
|
||||
Slow logs which include timestamps but no query--which can happen if using slow_query_log_timestamp_always in Percona Server--were misparsed, resulting in an erroneous report. Now such no-query events show up in reports as ``/* No query */``.
|
||||
|
||||
* Fixed bug 1078838: pt-query-digest doesn't parse general log with "Connect user as user"
|
||||
|
||||
The "as" was misparsed and the following word would end up reported as the database; pt-query-digest now handles this correctly.
|
||||
|
||||
* Fixed bug 1015590: pt-mysql-summary doesn't handle renamed variables in Percona Server 5.5
|
||||
|
||||
Some renamed variables had caused the Percona Server section to work unreliably.
|
||||
|
||||
* Fixed bug 1074179: pt-table-checksum doesn't ignore tables for --replicate-check-only
|
||||
|
||||
When using --replicate-check-only, filter options like --databases and --tables were not applied.
|
||||
|
||||
* Fixed bug 886059: pt-heartbeat handles timezones inconsistently
|
||||
|
||||
Previously, pt-heartbeat respected the MySQL time zone, but this caused false readings (e.g. very high lag) with slaves running in different time zones. Now pt-heartbeat uses UTC regardless of the server or MySQL time zone.
|
||||
|
||||
* Fixed bug 1079341: pt-online-schema-change checks for foreign keys on MyISAM tables
|
||||
|
||||
Since MyISAM tables can't have foreign keys, and the tool uses the information_schema to find child tables, this could cause unnecessary load on the server.
|
||||
|
||||
2.1.8 continues the trend of solid bug fix releases, and all 2.1 users are encouraged to upgrade.
|
||||
|
||||
Percona Toolkit packages can be downloaded from http://www.percona.com/downloads/percona-toolkit/ or the Percona Software Repositories (http://www.percona.com/software/repositories/).
|
||||
|
||||
Changelog
|
||||
---------
|
||||
|
||||
* Beta support for MySQL 5.6
|
||||
* Beta support for Percona XtraDB Cluster
|
||||
* pt-online-schema-change: If ran on Percona XtraDB Cluster, requires PXC 5.5.28 or newer
|
||||
* pt-table-checksum: If ran on Percona XtraDB Cluster, requires PXC 5.5.28 or newer
|
||||
* pt-upgrade: Added --[no]disable-query-cache
|
||||
* Fixed bug 927955: Bad pod2rst transformation
|
||||
* Fixed bug 898665: Bad online docs formatting for --[no]vars
|
||||
* Fixed bug 1022622: pt-config-diff is case-sensitive
|
||||
* Fixed bug 1007938: pt-config-diff doesn't handle end-of-line comments
|
||||
* Fixed bug 917770: pt-config-diff Use of uninitialized value in substitution (s///) at line 1996
|
||||
* Fixed bug 1082104: pt-deadlock-logger doesn't handle usernames with dashes
|
||||
* Fixed bug 886059: pt-heartbeat handles timezones inconsistently
|
||||
* Fixed bug 1086259: pt-kill --log-dsn timestamp is wrong
|
||||
* Fixed bug 1015590: pt-mysql-summary doesn't handle renamed variables in Percona Server 5.5
|
||||
* Fixed bug 1079341: pt-online-schema-change checks for foreign keys on MyISAM tables
|
||||
* Fixed bug 823431: pt-query-advisor hangs on big queries
|
||||
* Fixed bug 996069: pt-query-advisor RES.001 is incorrect
|
||||
* Fixed bug 933465: pt-query-advisor false positive on RES.001
|
||||
* Fixed bug 937234: pt-query-advisor issues wrong RES.001
|
||||
* Fixed bug 1082599: pt-query-digest fails to parse timestamp with no query
|
||||
* Fixed bug 1078838: pt-query-digest doesn't parse general log with "Connect user as user"
|
||||
* Fixed bug 957442: pt-query-digest with custom --group-by throws error
|
||||
* Fixed bug 887638: pt-query-digest prints negative byte offset
|
||||
* Fixed bug 831525: pt-query-digest help output mangled
|
||||
* Fixed bug 932614: pt-slave-restart CHANGE MASTER query causes error
|
||||
* Fixed bug 1046440: pt-stalk purge_samples slows down checks
|
||||
* Fixed bug 986847: pt-stalk does not report NFS iostat
|
||||
* Fixed bug 1074179: pt-table-checksum doesn't ignore tables for --replicate-check-only
|
||||
* Fixed bug 911385: pt-table-checksum v2 fails when --resume + --ignore-database is used
|
||||
* Fixed bug 1041391: pt-table-checksum debug statement for "Chosen hash func" prints undef
|
||||
* Fixed bug 1075638: pt-table-checksum Illegal division by zero at line 7950
|
||||
* Fixed bug 1052475: pt-table-checksum uninitialized value in numeric lt (<) at line 8611
|
||||
* Fixed bug 1078887: Tools let --set-vars clobber the required SQL mode
|
||||
|
||||
v2.1.7 released 2012-11-19
|
||||
==========================
|
||||
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# This program is copyright 2010-2011 Percona Inc.
|
||||
# This program is copyright 2010-2011 Percona Ireland Ltd.
|
||||
# Feedback and improvements are welcome.
|
||||
#
|
||||
# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# This program is copyright 2010-2011 Percona Inc.
|
||||
# This program is copyright 2010-2011 Percona Ireland Ltd.
|
||||
# Feedback and improvements are welcome.
|
||||
#
|
||||
# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# This program is copyright 2007-2011 Baron Schwartz, 2011 Percona Inc.
|
||||
# This program is copyright 2007-2011 Baron Schwartz, 2011 Percona Ireland Ltd.
|
||||
# Feedback and improvements are welcome.
|
||||
#
|
||||
# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# This program is copyright 2007-2011 Baron Schwartz, 2011 Percona Inc.
|
||||
# This program is copyright 2007-2011 Baron Schwartz, 2011 Percona Ireland Ltd.
|
||||
# Feedback and improvements are welcome.
|
||||
#
|
||||
# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# This program is copyright 2011 Percona Inc.
|
||||
# This program is copyright 2011 Percona Ireland Ltd.
|
||||
# Feedback and improvements are welcome.
|
||||
#
|
||||
# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# This program is copyright 2009-2011 Percona Inc.
|
||||
# This program is copyright 2009-2011 Percona Ireland Ltd.
|
||||
# Feedback and improvements are welcome.
|
||||
#
|
||||
# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
@@ -298,7 +298,7 @@ sub _report_diff_big {
|
||||
return unless keys %{$self->{diffs}->{big}};
|
||||
|
||||
my $report = new ReportFormatter();
|
||||
$report->set_title('Big query time differences');
|
||||
$report->title('Big query time differences');
|
||||
my $hostno = 0;
|
||||
$report->set_columns(
|
||||
$args{query_id_col},
|
||||
@@ -347,7 +347,7 @@ sub _report_diff_in_bucket {
|
||||
return unless keys %{$self->{diffs}->{in_bucket}};
|
||||
|
||||
my $report = new ReportFormatter();
|
||||
$report->set_title('Significant query time differences');
|
||||
$report->title('Significant query time differences');
|
||||
my $hostno = 0;
|
||||
$report->set_columns(
|
||||
$args{query_id_col},
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# This program is copyright 2009-2011 Percona Inc.
|
||||
# This program is copyright 2009-2011 Percona Ireland Ltd.
|
||||
# Feedback and improvements are welcome.
|
||||
#
|
||||
# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
@@ -874,7 +874,7 @@ sub _report_diff_checksums {
|
||||
return unless keys %{$self->{diffs}->{checksums}};
|
||||
|
||||
my $report = new ReportFormatter();
|
||||
$report->set_title('Checksum differences');
|
||||
$report->title('Checksum differences');
|
||||
$report->set_columns(
|
||||
$args{query_id_col},
|
||||
@{$args{host_cols}},
|
||||
@@ -905,7 +905,7 @@ sub _report_diff_col_vals {
|
||||
return unless keys %{$self->{diffs}->{col_vals}};
|
||||
|
||||
my $report = new ReportFormatter();
|
||||
$report->set_title('Column value differences');
|
||||
$report->title('Column value differences');
|
||||
$report->set_columns(
|
||||
$args{query_id_col},
|
||||
{
|
||||
@@ -940,7 +940,7 @@ sub _report_diff_row_counts {
|
||||
return unless keys %{$self->{diffs}->{row_counts}};
|
||||
|
||||
my $report = new ReportFormatter();
|
||||
$report->set_title('Row count differences');
|
||||
$report->title('Row count differences');
|
||||
my $hostno = 0;
|
||||
$report->set_columns(
|
||||
$args{query_id_col},
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# This program is copyright 2009-2011 Percona Inc.
|
||||
# This program is copyright 2009-2011 Percona Ireland Ltd.
|
||||
# Feedback and improvements are welcome.
|
||||
#
|
||||
# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
@@ -324,7 +324,7 @@ sub _report_diff_warnings {
|
||||
return unless keys %{$self->{diffs}->{warnings}};
|
||||
|
||||
my $report = new ReportFormatter(extend_right => 1);
|
||||
$report->set_title('New warnings');
|
||||
$report->title('New warnings');
|
||||
$report->set_columns(
|
||||
$args{query_id_col},
|
||||
{ name => 'Host', },
|
||||
@@ -358,7 +358,7 @@ sub _report_diff_levels {
|
||||
return unless keys %{$self->{diffs}->{levels}};
|
||||
|
||||
my $report = new ReportFormatter(extend_right => 1);
|
||||
$report->set_title('Warning level differences');
|
||||
$report->title('Warning level differences');
|
||||
my $hostno = 0;
|
||||
$report->set_columns(
|
||||
$args{query_id_col},
|
||||
@@ -396,7 +396,7 @@ sub _report_diff_warning_counts {
|
||||
return unless keys %{$self->{diffs}->{warning_counts}};
|
||||
|
||||
my $report = new ReportFormatter();
|
||||
$report->set_title('Warning count differences');
|
||||
$report->title('Warning count differences');
|
||||
my $hostno = 0;
|
||||
$report->set_columns(
|
||||
$args{query_id_col},
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# This program is copyright 2011 Percona Inc.
|
||||
# This program is copyright 2011 Percona Ireland Ltd.
|
||||
# Feedback and improvements are welcome.
|
||||
#
|
||||
# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# This program is copyright 2011 Percona Inc.
|
||||
# This program is copyright 2011 Percona Ireland Ltd.
|
||||
# Feedback and improvements are welcome.
|
||||
#
|
||||
# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# This program is copyright 2007-2011 Baron Schwartz, 2011 Percona Inc.
|
||||
# This program is copyright 2007-2011 Baron Schwartz, 2011 Percona Ireland Ltd.
|
||||
# Feedback and improvements are welcome.
|
||||
#
|
||||
# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# This program is copyright 2008-2011 Percona Inc.
|
||||
# This program is copyright 2008-2011 Percona Ireland Ltd.
|
||||
# Feedback and improvements are welcome.
|
||||
#
|
||||
# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# This program is copyright 2011 Percona Inc.
|
||||
# This program is copyright 2011 Percona Ireland Ltd.
|
||||
# Feedback and improvements are welcome.
|
||||
#
|
||||
# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# This program is copyright 2011 Percona Inc.
|
||||
# This program is copyright 2011 Percona Ireland Ltd.
|
||||
# Feedback and improvements are welcome.
|
||||
#
|
||||
# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# This program is copyright 2011 Percona Inc.
|
||||
# This program is copyright 2011 Percona Ireland Ltd.
|
||||
# Feedback and improvements are welcome.
|
||||
#
|
||||
# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# This program is copyright 2011 Percona Inc.
|
||||
# This program is copyright 2011 Percona Ireland Ltd.
|
||||
# Feedback and improvements are welcome.
|
||||
#
|
||||
# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# This program is copyright 2011 Percona Inc.
|
||||
# This program is copyright 2011 Percona Ireland Ltd.
|
||||
# Feedback and improvements are welcome.
|
||||
#
|
||||
# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# This program is copyright 2009-2011 Percona Inc.
|
||||
# This program is copyright 2009-2011 Percona Ireland Ltd.
|
||||
# Feedback and improvements are welcome.
|
||||
#
|
||||
# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# This program is copyright 2008-2011 Percona Inc.
|
||||
# This program is copyright 2008-2011 Percona Ireland Ltd.
|
||||
# Feedback and improvements are welcome.
|
||||
#
|
||||
# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# This program is copyright 2008-2011 Percona Inc.
|
||||
# This program is copyright 2008-2011 Percona Ireland Ltd.
|
||||
# Feedback and improvements are welcome.
|
||||
#
|
||||
# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# This program is copyright 2009-2011 Percona Inc.
|
||||
# This program is copyright 2009-2011 Percona Ireland Ltd.
|
||||
# Feedback and improvements are welcome.
|
||||
#
|
||||
# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# This program is copyright 2010-2011 Percona Inc.
|
||||
# This program is copyright 2010-2011 Percona Ireland Ltd.
|
||||
# Feedback and improvements are welcome.
|
||||
#
|
||||
# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# This program is copyright 2010-2011 Percona Inc.
|
||||
# This program is copyright 2010-2011 Percona Ireland Ltd.
|
||||
# Feedback and improvements are welcome.
|
||||
#
|
||||
# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# This program is copyright 2009-2011 Percona Inc.
|
||||
# This program is copyright 2009-2011 Percona Ireland Ltd.
|
||||
# Feedback and improvements are welcome.
|
||||
#
|
||||
# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# This program is copyright 2012-2013 Percona Inc.
|
||||
# This program is copyright 2012 Percona Ireland Ltd.
|
||||
# Feedback and improvements are welcome.
|
||||
#
|
||||
# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# This program is copyright 2009-2011 Percona Inc.
|
||||
# This program is copyright 2009-2011 Percona Ireland Ltd.
|
||||
# Feedback and improvements are welcome.
|
||||
#
|
||||
# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# This program is copyright 2012 Percona Inc.
|
||||
# This program is copyright 2012 Percona Ireland Ltd.
|
||||
# Feedback and improvements are welcome.
|
||||
#
|
||||
# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# This program is copyright 2010-2011 Percona Inc.
|
||||
# This program is copyright 2010-2011 Percona Ireland Ltd.
|
||||
# Feedback and improvements are welcome.
|
||||
#
|
||||
# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
|
@@ -1,14 +1,14 @@
|
||||
{
|
||||
package JSONReportFormatter;
|
||||
use Mo;
|
||||
use JSON ();
|
||||
|
||||
use List::Util qw(sum);
|
||||
|
||||
use List::Util qw(sum);
|
||||
use Transformers qw(make_checksum parse_timestamp);
|
||||
|
||||
use constant PTDEBUG => $ENV{PTDEBUG} || 0;
|
||||
|
||||
my $have_json = eval { require JSON };
|
||||
|
||||
our $pretty_json = undef;
|
||||
our $sorted_json = undef;
|
||||
|
||||
@@ -18,11 +18,23 @@ has _json => (
|
||||
is => 'ro',
|
||||
init_arg => undef,
|
||||
builder => '_build_json',
|
||||
handles => { encode_json => 'encode' },
|
||||
);
|
||||
|
||||
sub _build_json {
|
||||
return JSON->new->utf8->pretty($pretty_json)->canonical($sorted_json);
|
||||
return unless $have_json;
|
||||
return JSON->new->utf8
|
||||
->pretty($pretty_json)
|
||||
->canonical($sorted_json);
|
||||
}
|
||||
|
||||
sub encode_json {
|
||||
my ($self, $encode) = @_;
|
||||
if ( my $json = $self->_json ) {
|
||||
return $json->encode($encode);
|
||||
}
|
||||
else {
|
||||
return Transformers::encode_json($encode);
|
||||
}
|
||||
}
|
||||
|
||||
override [qw(rusage date hostname files header profile prepared)] => sub {
|
||||
@@ -103,7 +115,9 @@ override query_report => sub {
|
||||
};
|
||||
}
|
||||
|
||||
return $self->encode_json(\@queries) . "\n";
|
||||
my $json = $self->encode_json(\@queries);
|
||||
$json .= "\n" if $json !~ /\n\Z/;
|
||||
return $json . "\n";
|
||||
};
|
||||
|
||||
1;
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# This program is copyright 2008-2011 Percona Inc.
|
||||
# This program is copyright 2008-2011 Percona Ireland Ltd.
|
||||
# Feedback and improvements are welcome.
|
||||
#
|
||||
# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# This program is copyright 2007-2011 Baron Schwartz, 2011-2012 Percona Inc.
|
||||
# This program is copyright 2007-2011 Baron Schwartz, 2011-2012 Percona Ireland Ltd.
|
||||
# Feedback and improvements are welcome.
|
||||
#
|
||||
# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# This program is copyright 2009-2011 Percona Inc.
|
||||
# This program is copyright 2009-2011 Percona Ireland Ltd.
|
||||
# Feedback and improvements are welcome.
|
||||
#
|
||||
# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# This program is copyright 2007-2011 Percona Inc.
|
||||
# This program is copyright 2007-2011 Percona Ireland Ltd.
|
||||
# Feedback and improvements are welcome.
|
||||
#
|
||||
# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# This program is copyright 2010-2011 Percona Inc.
|
||||
# This program is copyright 2010-2011 Percona Ireland Ltd.
|
||||
# Feedback and improvements are welcome.
|
||||
#
|
||||
# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# This program is copyright 2010-2011 Percona Inc.
|
||||
# This program is copyright 2010-2011 Percona Ireland Ltd.
|
||||
# Feedback and improvements are welcome.
|
||||
#
|
||||
# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# This program is copyright 2007-2011 Percona Inc.
|
||||
# This program is copyright 2007-2011 Percona Ireland Ltd.
|
||||
# Feedback and improvements are welcome.
|
||||
#
|
||||
# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# This program is copyright 2011 Percona Inc.
|
||||
# This program is copyright 2011 Percona Ireland Ltd.
|
||||
# Feedback and improvements are welcome.
|
||||
#
|
||||
# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# This program is copyright 2011 Percona Inc.
|
||||
# This program is copyright 2011 Percona Ireland Ltd.
|
||||
# Feedback and improvements are welcome.
|
||||
#
|
||||
# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# This program is copyright 2011 Percona Inc.
|
||||
# This program is copyright 2011 Percona Ireland Ltd.
|
||||
# Feedback and improvements are welcome.
|
||||
#
|
||||
# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# This program is copyright 2007-2011 Baron Schwartz, 2011 Percona Inc.
|
||||
# This program is copyright 2007-2011 Baron Schwartz, 2011 Percona Ireland Ltd.
|
||||
# Feedback and improvements are welcome.
|
||||
#
|
||||
# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# This program is copyright 2009-2011 Percona Inc.
|
||||
# This program is copyright 2009-2011 Percona Ireland Ltd.
|
||||
# Feedback and improvements are welcome.
|
||||
#
|
||||
# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# This program is copyright 2012 Percona Inc.
|
||||
# This program is copyright 2012-2013 Percona Ireland Ltd.
|
||||
# Feedback and improvements are welcome.
|
||||
#
|
||||
# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# This program is copyright 2009-2011 Percona Inc.
|
||||
# This program is copyright 2009-2011 Percona Ireland Ltd.
|
||||
# Feedback and improvements are welcome.
|
||||
#
|
||||
# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# This program is copyright 2010-2011 Baron Schwartz, 2011 Percona Inc.
|
||||
# This program is copyright 2010-2011 Baron Schwartz, 2011 Percona Ireland Ltd.
|
||||
# Feedback and improvements are welcome.
|
||||
#
|
||||
# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# This program is copyright 2011 Percona Inc.
|
||||
# This program is copyright 2011 Percona Ireland Ltd.
|
||||
# Feedback and improvements are welcome.
|
||||
#
|
||||
# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# This program is copyright 2010-2011 Percona Inc.
|
||||
# This program is copyright 2010-2011 Percona Ireland Ltd.
|
||||
# Feedback and improvements are welcome.
|
||||
#
|
||||
# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# This program is copyright 2008-2011 Baron Schwartz, 2011 Percona Inc.
|
||||
# This program is copyright 2008-2011 Baron Schwartz, 2011 Percona Ireland Ltd.
|
||||
# Feedback and improvements are welcome.
|
||||
#
|
||||
# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# This program is copyright 2010-2011 Percona Inc.
|
||||
# This program is copyright 2010-2011 Percona Ireland Ltd.
|
||||
# Feedback and improvements are welcome.
|
||||
#
|
||||
# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# This program is copyright 2009-2011 Percona Inc.
|
||||
# This program is copyright 2009-2011 Percona Ireland Ltd.
|
||||
# Feedback and improvements are welcome.
|
||||
#
|
||||
# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# This program is copyright 2010-2011 Percona Inc.
|
||||
# This program is copyright 2010-2011 Percona Ireland Ltd.
|
||||
# Feedback and improvements are welcome.
|
||||
#
|
||||
# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# This program is copyright 2008-2011 Percona Inc.
|
||||
# This program is copyright 2008-2011 Percona Ireland Ltd.
|
||||
# Feedback and improvements are welcome.
|
||||
#
|
||||
# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# This program is copyright 2008-2011 Percona Inc.
|
||||
# This program is copyright 2008-2011 Percona Ireland Ltd.
|
||||
# Feedback and improvements are welcome.
|
||||
#
|
||||
# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# This program is copyright 2008-2011 Percona Inc.
|
||||
# This program is copyright 2008-2011 Percona Ireland Ltd.
|
||||
# Feedback and improvements are welcome.
|
||||
#
|
||||
# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# This program is copyright 2007-2011 Baron Schwartz, 2011 Percona Inc.
|
||||
# This program is copyright 2007-2011 Baron Schwartz, 2011 Percona Ireland Ltd.
|
||||
# Feedback and improvements are welcome.
|
||||
#
|
||||
# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# This program is copyright 2007-2011 Baron Schwartz, 2011 Percona Inc.
|
||||
# This program is copyright 2007-2011 Baron Schwartz, 2011 Percona Ireland Ltd.
|
||||
# Feedback and improvements are welcome.
|
||||
#
|
||||
# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# This program is copyright 2012 Percona Inc.
|
||||
# This program is copyright 2012 Percona Ireland Ltd.
|
||||
# Feedback and improvements are welcome.
|
||||
#
|
||||
# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# This program is copyright 2010-2012 Percona Inc.
|
||||
# This program is copyright 2010-2012 Percona Ireland Ltd.
|
||||
# Feedback and improvements are welcome.
|
||||
#
|
||||
# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# This program is copyright 2011 Percona Inc.
|
||||
# This program is copyright 2011 Percona Ireland Ltd.
|
||||
# Feedback and improvements are welcome.
|
||||
#
|
||||
# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# This program is copyright 2009-2011 Percona Inc.
|
||||
# This program is copyright 2009-2011 Percona Ireland Ltd.
|
||||
# Feedback and improvements are welcome.
|
||||
#
|
||||
# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# This program is copyright 2010-2011 Percona Inc.
|
||||
# This program is copyright 2010-2011 Percona Ireland Ltd.
|
||||
# Feedback and improvements are welcome.
|
||||
#
|
||||
# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# This program is copyright 2007-2011 Baron Schwartz, 2011 Percona Inc.
|
||||
# This program is copyright 2007-2011 Baron Schwartz, 2011 Percona Ireland Ltd.
|
||||
# Feedback and improvements are welcome.
|
||||
#
|
||||
# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user