summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGreg Sabino Mullane2010-05-20 21:06:54 +0000
committerGreg Sabino Mullane2010-05-20 21:06:54 +0000
commit0955ab6f2edaf3fa6e0ee82d2cb0e1430e5a7881 (patch)
treee511a5fe84ae2928fbcb78d386cb53429fb2fe5f
parent0d4a33ce56950d0fb8f53ce273c208dbf0daca9f (diff)
Lots more checking of index information inside of same_schema.
Add tests for the same.
-rwxr-xr-xcheck_postgres.pl165
-rw-r--r--t/02_same_schema.t71
2 files changed, 201 insertions, 35 deletions
diff --git a/check_postgres.pl b/check_postgres.pl
index 3b2c11558..e9a4810eb 100755
--- a/check_postgres.pl
+++ b/check_postgres.pl
@@ -5096,7 +5096,34 @@ WHERE n1.nspname !~ 'pg_'
$thing{$x}{constraints}{"$ts.$tn"}{$name} = [$type,$key,$src];
}
}
- }
+ } ## end of constraints
+
+ ## Get a list of all index information
+ if (! exists $filter{noindexes}) {
+ $SQL = q{
+SELECT n.nspname, c1.relname AS tname, c2.relname AS iname, indisunique, indisprimary, indisclustered, indisvalid, indkey
+FROM pg_index i
+JOIN pg_class c1 ON (c1.oid = indrelid)
+JOIN pg_class c2 ON (c2.oid = indexrelid)
+JOIN pg_namespace n ON (n.oid = c2.relnamespace)
+WHERE nspname !~ 'pg_'
+};
+ $info = run_command($SQL, { dbuser => $opt{dbuser}[$x-1], dbnumber => $x } );
+ for $db (@{$info->{db}}) {
+ for my $r (@{$db->{slurp}}) {
+ my ($schema,$tname,$iname,$uniq,$pri,$clust,$valid,$key) = @$r{
+ qw/ nspname tname iname indisunique indisprimary indisclustered indisvalid indkey/};
+ $thing{$x}{indexinfo}{"$schema.$iname"} = {
+ table => "$schema.$tname",
+ isunique => $uniq,
+ isprimary => $pri,
+ isclustered => $clust,
+ isvalid => $valid,
+ key => $key,
+ };
+ }
+ }
+ } ## end of indexes
## Get a list of all functions
if (! exists $filter{nofunctions}) {
@@ -5122,7 +5149,7 @@ JOIN pg_namespace n ON (n.oid = pronamespace)
};
}
}
- }
+ } ## end of functions
## Get a list of all languages
if (! exists $filter{nolanguages}) {
@@ -5138,6 +5165,7 @@ JOIN pg_namespace n ON (n.oid = pronamespace)
} ## end each database to query
+
$db = $saved_db;
## Build a list of what has failed
@@ -5556,7 +5584,49 @@ JOIN pg_namespace n ON (n.oid = pronamespace)
$failcount++;
next;
}
- }
+
+ ## Do they both have the same information?
+ next if ! exists $thing{1}{indexinfo}{$name}
+ or ! exists $thing{2}{indexinfo}{$name};
+
+ my $one = $thing{1}{indexinfo}{$name};
+ my $two = $thing{2}{indexinfo}{$name};
+
+ if ($one->{table} ne $two->{table}) {
+ $fail{indexes}{table}{$name} = [$one->{table},$two->{table}];
+ $failcount++;
+ next;
+ }
+
+ for my $var (qw/isprimary isunique isclustered isvalid/) {
+ if ($one->{$var} ne $two->{$var}) {
+ $fail{indexes}{$var}{$name} = [$one->{$var},$two->{$var}];
+ $failcount++;
+ }
+ }
+
+ my $tname = $one->{table};
+ if (! exists $thing{1}{colmap}{$tname}) {
+ for my $col (keys %{$thing{1}{columns}{$tname}}) {
+ my $attnum = $thing{1}{columns}{$tname}{$col}{attnum};
+ $thing{1}{colmap}{$tname}{$attnum} = $col;
+ }
+ }
+ if (! exists $thing{2}{colmap}{$tname}) {
+ for my $col (keys %{$thing{2}{columns}{$tname}}) {
+ my $attnum = $thing{2}{columns}{$tname}{$col}{attnum};
+ $thing{2}{colmap}{$tname}{$attnum} = $col;
+ }
+ }
+ (my $cols1 = $one->{key}) =~ s/(\d+)/$thing{1}{colmap}{$tname}{$1}/g;
+ (my $cols2 = $two->{key}) =~ s/(\d+)/$thing{2}{colmap}{$tname}{$1}/g;
+
+ if ($cols1 ne $cols2) {
+ $fail{indexes}{key}{$name} = [$cols1, $cols2];
+ $failcount++;
+ }
+
+ } ## end of index info
## Compare columns
@@ -5669,28 +5739,26 @@ JOIN pg_namespace n ON (n.oid = pronamespace)
## Are they on the same key?
## May be just column reordering, so we dig deep before calling it a problem
- if ($key1 ne $key2) {
- if (! exists $thing{1}{colmap}{$tname}) {
- for my $col (keys %{$thing{1}{columns}{$tname}}) {
- my $attnum = $thing{1}{columns}{$tname}{$col}{attnum};
- $thing{1}{colmap}{$tname}{$attnum} = $col;
- }
+ if (! exists $thing{1}{colmap}{$tname}) {
+ for my $col (keys %{$thing{1}{columns}{$tname}}) {
+ my $attnum = $thing{1}{columns}{$tname}{$col}{attnum};
+ $thing{1}{colmap}{$tname}{$attnum} = $col;
}
- if (! exists $thing{2}{colmap}{$tname}) {
- for my $col (keys %{$thing{2}{columns}{$tname}}) {
- my $attnum = $thing{2}{columns}{$tname}{$col}{attnum};
- $thing{2}{colmap}{$tname}{$attnum} = $col;
- }
+ }
+ if (! exists $thing{2}{colmap}{$tname}) {
+ for my $col (keys %{$thing{2}{columns}{$tname}}) {
+ my $attnum = $thing{2}{columns}{$tname}{$col}{attnum};
+ $thing{2}{colmap}{$tname}{$attnum} = $col;
}
- (my $ckey1 = $key1) =~ s/(\d+)/$thing{1}{colmap}{$tname}{$1}/g;
- (my $ckey2 = $key2) =~ s/(\d+)/$thing{2}{colmap}{$tname}{$1}/g;
+ }
+ (my $ckey1 = $key1) =~ s/(\d+)/$thing{1}{colmap}{$tname}{$1}/g;
+ (my $ckey2 = $key2) =~ s/(\d+)/$thing{2}{colmap}{$tname}{$1}/g;
- if ($ckey1 ne $ckey2) {
- push @{$fail{constraints}{diffkey}} => [$cname, $tname, $ckey1, $ckey2];
- $failcount++;
- }
- ## No next here: we want to check the source as well
+ if ($ckey1 ne $ckey2) {
+ push @{$fail{constraints}{diffkey}} => [$cname, $tname, $ckey1, $ckey2];
+ $failcount++;
}
+ ## No next here: we want to check the source as well
## Only bother with the source for check constraints
next C22 if $type1 ne 'c';
@@ -6084,19 +6152,52 @@ JOIN pg_namespace n ON (n.oid = pronamespace)
## Index differences
if (exists $fail{indexes}){
- if (exists $fail{indexes}{notexist}) {
- if (exists $fail{indexes}{notexist}{1}) {
- for my $name (@{$fail{indexes}{notexist}{1}}) {
- $db->{perf} .= " Index on 1 but not 2: $name ";
- }
+ if (exists $fail{indexes}{notexist}) {
+ if (exists $fail{indexes}{notexist}{1}) {
+ for my $name (@{$fail{indexes}{notexist}{1}}) {
+ $db->{perf} .= " Index on 1 but not 2: $name ";
+ }
+ }
+ if (exists $fail{indexes}{notexist}{2}) {
+ for my $name (@{$fail{indexes}{notexist}{2}}) {
+ $db->{perf} .= " Index on 2 but not 1: $name ";
+ }
+ }
}
- if (exists $fail{indexes}{notexist}{2}) {
- for my $name (@{$fail{indexes}{notexist}{2}}) {
- $db->{perf} .= " Index on 2 but not 1: $name ";
- }
+
+ for my $name (sort keys %{$fail{indexes}{table}}) {
+ my ($one,$two) = @{$fail{indexes}{table}{$name}};
+ $db->{perf} .= sprintf ' Index %s is applied to table %s on 1, but to table %s on 2 ',
+ $name,
+ $one,
+ $two;
}
- }
- }
+
+ for my $var (qw/isprimary isunique isclustered isvalid/) {
+ for my $name (sort keys %{$fail{indexes}{$var}}) {
+ my ($one,$two) = @{$fail{indexes}{$var}{$name}};
+ (my $pname = $var) =~ s/^is//;
+ $pname = 'primary key' if $pname eq 'primary';
+ $db->{perf} .= sprintf ' Index %s is %s as %s on 1, but %s as %s on 2 ',
+ $name,
+ $one eq 't' ? 'set' : 'not set',
+ $pname,
+ $two eq 't' ? 'set' : 'not set',
+ $pname;
+ }
+ }
+
+ for my $name (sort keys %{$fail{indexes}{key}}) {
+ my ($one,$two) = @{$fail{indexes}{key}{$name}};
+ $db->{perf} .= sprintf ' Index %s is applied to %s %s on 1, but %s on 2 ',
+ $name,
+ $one =~ / / ? 'columns' : 'column',
+ $one,
+ $two;
+ }
+
+ } ## end of indexes
+
## Column differences
if (exists $fail{columns}) {
diff --git a/t/02_same_schema.t b/t/02_same_schema.t
index 1623df170..de49c95b7 100644
--- a/t/02_same_schema.t
+++ b/t/02_same_schema.t
@@ -6,7 +6,7 @@ use 5.006;
use strict;
use warnings;
use Data::Dumper;
-use Test::More tests => 50;
+use Test::More tests => 59;
use lib 't','.';
use CP_Testing;
@@ -395,8 +395,8 @@ $dbh2->do('DROP LANGUAGE plpgsql');
#/////////// Indexes
-$dbh1->do(q{CREATE TABLE table_1_only (a int, b text)});
-$dbh2->do(q{CREATE TABLE table_1_only (a int, b text)});
+$dbh1->do(q{CREATE TABLE table_1_only (a INT NOT NULL, b TEXT NOT NULL)});
+$dbh2->do(q{CREATE TABLE table_1_only (a INT NOT NULL, b TEXT NOT NULL)});
$t = qq{$S works when indexes are the same};
$dbh1->do(q{CREATE INDEX index_1 ON table_1_only(a)});
@@ -418,4 +418,69 @@ like ($cp1->run($stdargs),
qr{^$label CRITICAL:.*Index on 2 but not 1: public.index_3},
$t);
+$dbh1->do(q{SET client_min_messages = 'ERROR'});
+$dbh2->do(q{SET client_min_messages = 'ERROR'});
+
+$t = qq{$S fails when database 1 index is primary but 2 is not};
+$dbh1->do(q{ALTER TABLE table_1_only ADD CONSTRAINT index_3 PRIMARY KEY (a,b)});
+$dbh1->do(q{CLUSTER table_1_only USING index_3});
+like ($cp1->run($stdargs),
+ qr{^$label CRITICAL:.*Index public.index_3 is set as primary key on 1, but not set as primary key on 2},
+ $t);
+$t = qq{$S fails when database 1 index is unique but 2 is not};
+like ($cp1->run($stdargs),
+ qr{^$label CRITICAL:.*Index public.index_3 is set as unique on 1, but not set as unique on 2},
+ $t);
+$t = qq{$S fails when database 1 index is clustered but 2 is not};
+like ($cp1->run($stdargs),
+ qr{^$label CRITICAL:.*Index public.index_3 is set as clustered on 1, but not set as clustered on 2},
+ $t);
+
+$t = qq{$S fails when database 2 index is primary but 1 is not};
+$dbh1->do(q{ALTER TABLE table_1_only DROP CONSTRAINT index_3});
+$dbh1->do(q{CREATE INDEX index_3 ON table_1_only(a,b)});
+$dbh1->do(q{ALTER TABLE table_1_only SET WITHOUT CLUSTER});
+$dbh2->do(q{DROP INDEX index_3});
+$dbh2->do(q{ALTER TABLE table_1_only ADD CONSTRAINT index_3 PRIMARY KEY (a,b)});
+$dbh2->do(q{CLUSTER table_1_only USING index_3});
+like ($cp1->run($stdargs),
+ qr{^$label CRITICAL:.*Index public.index_3 is not set as primary key on 1, but set as primary key on 2},
+ $t);
+$t = qq{$S fails when database 2 index is unique but 1 is not};
+like ($cp1->run($stdargs),
+ qr{^$label CRITICAL:.*Index public.index_3 is not set as unique on 1, but set as unique on 2},
+ $t);
+$t = qq{$S fails when database 2 index is clustered but 1 is not};
+like ($cp1->run($stdargs),
+ qr{^$label CRITICAL:.*Index public.index_3 is not set as clustered on 1, but set as clustered on 2},
+ $t);
+
+$t = qq{$S fails when database 1 index is on different columns than database 2};
+$dbh1->do(q{CREATE INDEX index_4 ON table_1_only(a)});
+$dbh2->do(q{CREATE INDEX index_4 ON table_1_only(b)});
+like ($cp1->run($stdargs),
+ qr{^$label CRITICAL:.*Index public.index_4 is applied to column a on 1, but b on 2},
+ $t);
+
+$dbh1->do(q{DROP INDEX index_4});
+$dbh1->do(q{CREATE INDEX index_4 ON table_1_only(b,a)});
+like ($cp1->run($stdargs),
+ qr{^$label CRITICAL:.*Index public.index_4 is applied to columns b a on 1, but b on 2},
+ $t);
+
+
+$dbh1->do(q{DROP TABLE table_1_only});
+$dbh2->do(q{DROP TABLE table_1_only});
+$dbh1->do(q{CREATE TABLE table_1_only (a INT NOT NULL, b TEXT NOT NULL)});
+$dbh2->do(q{CREATE TABLE table_2_only (a INT NOT NULL, b TEXT NOT NULL)});
+$dbh1->do(q{CREATE INDEX index_5 ON table_1_only(a)});
+$dbh2->do(q{CREATE INDEX index_5 ON table_2_only(a)});
+
+like ($cp1->run($stdargs),
+ qr{^$label CRITICAL:.*Index public.index_5 is applied to table public.table_1_only on 1, but to table public.table_2_only on 2},
+ $t);
+
+$dbh1->do('DROP TABLE table_1_only');
+$dbh2->do('DROP TABLE table_2_only');
+
exit;