mirror of
https://github.com/percona/percona-toolkit.git
synced 2025-09-01 18:25:59 +00:00

* Fix typos in lib/ directory * Update generated bin/ files * PR 655 - War on typos Act 1 #655 - Updated modules in tools that were not updated - Fixed tests to reflect proposed changes --------- Co-authored-by: Sveta Smirnova <sveta.smirnova@percona.com>
270 lines
7.8 KiB
Perl
270 lines
7.8 KiB
Perl
# 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
|
|
# 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.
|
|
# ###########################################################################
|
|
# Schema package
|
|
# ###########################################################################
|
|
{
|
|
# Package: Schema
|
|
# Schema encapsulates a data structure representing databases and tables.
|
|
# Although in MySQL "schema" is technically equivalent to "database", we
|
|
# use "schema" loosely to mean a collection of schema objects: databases,
|
|
# tables, and columns. These objects are organized in a hash keyed on
|
|
# database and table names. The hash is called schema and looks like,
|
|
# (start code)
|
|
# db1 => {
|
|
# tbl1 => {
|
|
# db => 'db1',
|
|
# tbl => 'tbl1',
|
|
# tbl_struct => <TableParser::parse()>
|
|
# ddl => "CREATE TABLE `tbl` ( ...",
|
|
# }
|
|
# }
|
|
# (stop code)
|
|
# Each table has at least a db and tbl key and probably a tbl_struct.
|
|
#
|
|
# The important thing about a Schema object is that it should be the only
|
|
# data structure with this data, and other modules should reference and add
|
|
# data to it rather than creating other similar copies. <ColumnMap> does
|
|
# this for example.
|
|
#
|
|
# The other important thing about a Schema object is that the data structure
|
|
# is the standard. Other modules should take db or tbl hashrefs pointing
|
|
# into the data structure. Tbl hashrefs should always have at least at db
|
|
# and tbl key (which is redundant but necessary so that each tbl hashref
|
|
# includes its own database and table name).
|
|
#
|
|
# Schema objects are usually added by a <SchemaIterator>, but you can add
|
|
# them manually if needed; see <add_schema_object()>.
|
|
package Schema;
|
|
|
|
use strict;
|
|
use warnings FATAL => 'all';
|
|
use English qw(-no_match_vars);
|
|
use constant PTDEBUG => $ENV{PTDEBUG} || 0;
|
|
|
|
# Sub: new
|
|
#
|
|
# Parameters:
|
|
# %args - Arguments
|
|
#
|
|
# Returns:
|
|
# Schema object
|
|
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 = {
|
|
%args,
|
|
schema => {}, # keyed on db->tbl
|
|
# columns => {}, # No tools use is_duplicate_table() or
|
|
# tables => {}, # is_duplicate_column() yet...
|
|
};
|
|
return bless $self, $class;
|
|
}
|
|
|
|
sub get_schema {
|
|
my ( $self ) = @_;
|
|
return $self->{schema};
|
|
}
|
|
|
|
sub get_table {
|
|
my ( $self, $db_name, $tbl_name ) = @_;
|
|
if ( exists $self->{schema}->{$db_name}
|
|
&& exists $self->{schema}->{$db_name}->{$tbl_name} ) {
|
|
return $self->{schema}->{$db_name}->{$tbl_name};
|
|
}
|
|
return;
|
|
}
|
|
|
|
#sub is_duplicate_column {
|
|
# my ( $self, $col ) = @_;
|
|
# return unless $col;
|
|
# return ($self->{columns}->{$col} || 0) > 1 ? 1 : 0;
|
|
#}
|
|
|
|
#sub is_duplicate_table {
|
|
# my ( $self, $tbl ) = @_;
|
|
# return unless $tbl;
|
|
# return ($self->{tables}->{$tbl} || 0) > 1 ? 1 : 0;
|
|
#}
|
|
|
|
# Sub: add_schema_object
|
|
# Add a schema object. This sub is called by
|
|
# <SchemaIterator::next_schema_object()>.
|
|
#
|
|
# Parameters:
|
|
# $schema_object - Schema object hashref.
|
|
sub add_schema_object {
|
|
my ( $self, $schema_object ) = @_;
|
|
die "I need a schema_object argument" unless $schema_object;
|
|
|
|
my ($db, $tbl) = @{$schema_object}{qw(db tbl)};
|
|
if ( !$db || !$tbl ) {
|
|
warn "No database or table for schema object";
|
|
return;
|
|
}
|
|
|
|
my $tbl_struct = $schema_object->{tbl_struct};
|
|
if ( !$tbl_struct ) {
|
|
warn "No table structure for $db.$tbl";
|
|
return;
|
|
}
|
|
|
|
# Add/save this schema object.
|
|
$self->{schema}->{lc $db}->{lc $tbl} = $schema_object;
|
|
|
|
# Get duplicate column and table names.
|
|
# map { $self->{columns}->{lc $_}++ } @{$tbl_struct->{cols}};
|
|
# $self->{tables}->{lc $tbl_struct->{name}}++;
|
|
|
|
return;
|
|
}
|
|
|
|
sub find_column {
|
|
my ( $self, %args ) = @_;
|
|
my $ignore = $args{ignore};
|
|
my $schema = $self->{schema};
|
|
|
|
my ($col, $tbl, $db);
|
|
if ( my $col_name = $args{col_name} ) {
|
|
($col, $tbl, $db) = reverse map { s/`//g; $_ } split /[.]/, $col_name;
|
|
PTDEBUG && _d('Column', $col_name, 'has db', $db, 'tbl', $tbl,
|
|
'col', $col);
|
|
}
|
|
else {
|
|
($col, $tbl, $db) = @args{qw(col tbl db)};
|
|
}
|
|
|
|
$db = lc($db || '');
|
|
$tbl = lc($tbl || '');
|
|
$col = lc($col || '');
|
|
|
|
if ( !$col ) {
|
|
PTDEBUG && _d('No column specified or parsed');
|
|
return;
|
|
}
|
|
PTDEBUG && _d('Finding column', $col, 'in', $db, $tbl);
|
|
|
|
if ( $db && !$schema->{$db} ) {
|
|
PTDEBUG && _d('Database', $db, 'does not exist');
|
|
return;
|
|
}
|
|
|
|
if ( $db && $tbl && !$schema->{$db}->{$tbl} ) {
|
|
PTDEBUG && _d('Table', $tbl, 'does not exist in database', $db);
|
|
return;
|
|
}
|
|
|
|
my @tbls;
|
|
my @search_dbs = $db ? ($db) : keys %$schema;
|
|
DATABASE:
|
|
foreach my $search_db ( @search_dbs ) {
|
|
my @search_tbls = $tbl ? ($tbl) : keys %{$schema->{$search_db}};
|
|
|
|
TABLE:
|
|
foreach my $search_tbl ( @search_tbls ) {
|
|
next DATABASE unless exists $schema->{$search_db}->{$search_tbl};
|
|
|
|
if ( $ignore
|
|
&& grep { $_->{db} eq $search_db && $_->{tbl} eq $search_tbl }
|
|
@$ignore ) {
|
|
PTDEBUG && _d('Ignoring', $search_db, $search_tbl, $col);
|
|
next TABLE;
|
|
}
|
|
|
|
my $tbl = $schema->{$search_db}->{$search_tbl};
|
|
if ( $tbl->{tbl_struct}->{is_col}->{$col} ) {
|
|
PTDEBUG && _d('Column', $col, 'exists in', $tbl->{db}, $tbl->{tbl});
|
|
push @tbls, $tbl;
|
|
}
|
|
}
|
|
}
|
|
|
|
@tbls = sort {$b->{name} cmp $a->{name}} @tbls;
|
|
return \@tbls;
|
|
|
|
}
|
|
|
|
sub find_table {
|
|
my ( $self, %args ) = @_;
|
|
my $ignore = $args{ignore};
|
|
my $schema = $self->{schema};
|
|
|
|
my ($tbl, $db);
|
|
if ( my $tbl_name = $args{tbl_name} ) {
|
|
($tbl, $db) = reverse map { s/`//g; $_ } split /[.]/, $tbl_name;
|
|
PTDEBUG && _d('Table', $tbl_name, 'has db', $db, 'tbl', $tbl);
|
|
}
|
|
else {
|
|
($tbl, $db) = @args{qw(tbl db)};
|
|
}
|
|
|
|
$db = lc($db || '');
|
|
$tbl = lc($tbl || '');
|
|
|
|
if ( !$tbl ) {
|
|
PTDEBUG && _d('No table specified or parsed');
|
|
return;
|
|
}
|
|
PTDEBUG && _d('Finding table', $tbl, 'in', $db);
|
|
|
|
if ( $db && !$schema->{$db} ) {
|
|
PTDEBUG && _d('Database', $db, 'does not exist');
|
|
return;
|
|
}
|
|
|
|
if ( $db && $tbl && !$schema->{$db}->{$tbl} ) {
|
|
PTDEBUG && _d('Table', $tbl, 'does not exist in database', $db);
|
|
return;
|
|
}
|
|
|
|
my @dbs;
|
|
my @search_dbs = $db ? ($db) : keys %$schema;
|
|
DATABASE:
|
|
foreach my $search_db ( @search_dbs ) {
|
|
if ( $ignore && grep { $_->{db} eq $search_db } @$ignore ) {
|
|
PTDEBUG && _d('Ignoring', $search_db);
|
|
next DATABASE;
|
|
}
|
|
|
|
if ( exists $schema->{$search_db}->{$tbl} ) {
|
|
PTDEBUG && _d('Table', $tbl, 'exists in', $search_db);
|
|
push @dbs, $search_db;
|
|
}
|
|
}
|
|
|
|
@dbs = sort @dbs;
|
|
return \@dbs;
|
|
}
|
|
|
|
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;
|
|
}
|
|
# ###########################################################################
|
|
# End Schema package
|
|
# ###########################################################################
|