mirror of
https://github.com/percona/percona-toolkit.git
synced 2025-09-11 05:29:30 +00:00
176 lines
5.3 KiB
Perl
176 lines
5.3 KiB
Perl
# This program is copyright 2010 Percona Inc.
|
|
# Feedback and improvements are welcome.
|
|
#
|
|
# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
|
|
# WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
|
# MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
|
#
|
|
# This program is free software; you can redistribute it and/or modify it under
|
|
# the terms of the GNU General Public License as published by the Free Software
|
|
# Foundation, version 2; OR the Perl Artistic License. On UNIX and similar
|
|
# systems, you can issue `man perlgpl' or `man perlartistic' to read these
|
|
# licenses.
|
|
#
|
|
# You should have received a copy of the GNU General Public License along with
|
|
# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
|
# Place, Suite 330, Boston, MA 02111-1307 USA.
|
|
|
|
package compact_col_vals;
|
|
|
|
# This mk-archiver plugin demonstrates how to compact a column's values.
|
|
# If a column has values {1, 3, 4, 9, 10} it is compacted to {1, 2, 3, 4, 5}
|
|
# (if $step=1). No other column values are changed. Column values are
|
|
# only compacted "downwards". So if $step=2, the value above are compacted
|
|
# to {1, 3, 4, 7, 9}.
|
|
#
|
|
# This modules does *not* allow any rows to be deleted. is_archivable()
|
|
# returns false for every row. Even if you specify --purge, the rows will
|
|
# not be purged. UPDATEs are made while the table is being nibbled.
|
|
# Options --dest and --file are not tested.
|
|
#
|
|
# If the compact column is AUTO_INCREMENT, you need to specify
|
|
# --no-safe-auto-incrment else the last row (i.e. the one with the highest
|
|
# auto inc value) will not be compacted.
|
|
#
|
|
# See compact_col_vals.sql for a before and after example.
|
|
|
|
use strict;
|
|
use warnings FATAL => 'all';
|
|
use English qw(-no_match_vars);
|
|
|
|
use constant MKDEBUG => $ENV{MKDEBUG} || 0;
|
|
|
|
use Data::Dumper;
|
|
$Data::Dumper::Indent = 1;
|
|
$Data::Dumper::Sortkeys = 1;
|
|
$Data::Dumper::Quotekeys = 0;
|
|
|
|
# ###########################################################################
|
|
# Customize these values for your tables.
|
|
# ###########################################################################
|
|
my $compact_column = 'id'; # column name to compact
|
|
my $step = 1; # amount by which column values should increase
|
|
|
|
|
|
# ###########################################################################
|
|
# Don't modify anything below here.
|
|
# ###########################################################################
|
|
sub new {
|
|
my ( $class, %args ) = @_;
|
|
my $o = $args{OptionParser};
|
|
my $q = $args{Quoter};
|
|
my $dbh = $args{dbh};
|
|
|
|
my $sth;
|
|
my $db_tbl = $q->quote($args{db}, $args{tbl});
|
|
my $sql = "UPDATE $db_tbl SET `$compact_column`=? "
|
|
. "WHERE `$compact_column`=?";
|
|
MKDEBUG && _d('sth:', $sql);
|
|
if ( !$o->get('dry-run') ) {
|
|
$sth = $dbh->prepare($sql);
|
|
}
|
|
else {
|
|
print "# compact_col_vals plugin\n$sql\n";
|
|
}
|
|
|
|
my $self = {
|
|
%args,
|
|
db_tbl => $db_tbl,
|
|
sth => $sth,
|
|
col_pos => undef,
|
|
next_val => 0,
|
|
};
|
|
|
|
return bless $self, $class;
|
|
}
|
|
|
|
sub before_begin {
|
|
my ( $self, %args ) = @_;
|
|
my $allcols = $args{allcols};
|
|
MKDEBUG && _d('allcols:', Dumper($allcols));
|
|
my $colpos = -1;
|
|
foreach my $col ( @$allcols ) {
|
|
$colpos++;
|
|
last if $col eq $compact_column;
|
|
}
|
|
if ( $colpos < 0 ) {
|
|
die "Column $compact_column not selected by mk-archiver: "
|
|
. join(', ', @$allcols);
|
|
}
|
|
MKDEBUG && _d('col pos:', $colpos);
|
|
$self->{col_pos} = $colpos;
|
|
return;
|
|
}
|
|
|
|
sub is_archivable {
|
|
my ( $self, %args ) = @_;
|
|
my $next_val = $self->{next_val};
|
|
my $row = $args{row};
|
|
my $val = $row->[$self->{col_pos}];
|
|
my $sth = $self->{sth};
|
|
MKDEBUG && _d('val:', $val);
|
|
|
|
if ( $next_val ){
|
|
if ( $val > $next_val ) {
|
|
MKDEBUG && _d('Updating', $val, 'to', $next_val);
|
|
$sth->execute($next_val, $val);
|
|
}
|
|
else {
|
|
MKDEBUG && _d('Val is OK');
|
|
}
|
|
}
|
|
else {
|
|
# This should happen once.
|
|
MKDEBUG && _d('First val:', $val);
|
|
$self->{next_val} = $val;
|
|
}
|
|
|
|
$self->{next_val}++;
|
|
MKDEBUG && _d('Next val should be', $self->{next_val});
|
|
|
|
# No rows are archivable because we're exploiting mk-archiver
|
|
# just for its ability to nibble the table. To be safe, return 0
|
|
# for every row so that any potential delete/purge operations
|
|
# will not happen.
|
|
return 0;
|
|
}
|
|
|
|
sub before_delete {
|
|
my ( $self, %args ) = @_;
|
|
# Because is_archivable() always returns 0, this sub should
|
|
# not be called by mk-archiver.
|
|
die "before_delete() was called but should not have been called!";
|
|
}
|
|
|
|
sub before_bulk_delete {
|
|
my ( $self, %args ) = @_;
|
|
# Because is_archivable() always returns 0, this sub should
|
|
# not be called by mk-archiver.
|
|
die "before_bulk_delete() was called but should not have been called!";
|
|
}
|
|
|
|
# Reset AUTO_INCREMENT to next, lowest value.
|
|
sub after_finish {
|
|
my ( $self ) = @_;
|
|
my $o = $self->{OptionParser};
|
|
my $sql = "ALTER TABLE $self->{db_tbl} AUTO_INCREMENT=$self->{next_val}";
|
|
if ( !$o->get('dry-run') ) {
|
|
MKDEBUG && _d($sql);
|
|
$self->{dbh}->do($sql);
|
|
}
|
|
else {
|
|
print "# compact_col_vals plugin\n$sql\n";
|
|
}
|
|
return;
|
|
}
|
|
|
|
sub _d {
|
|
my ($package, undef, $line) = caller 0;
|
|
@_ = map { (my $temp = $_) =~ s/\n/\n# /g; $temp; }
|
|
map { defined $_ ? $_ : 'undef' }
|
|
@_;
|
|
print STDERR "# $package:$line $PID ", join(' ', @_), "\n";
|
|
}
|
|
|
|
1;
|