Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Query all sequences per DB in parallel for action=sequence
authorChristoph Berg <christoph.berg@credativ.de>
Mon, 23 Mar 2015 14:52:49 +0000 (15:52 +0100)
committerChristoph Berg <christoph.berg@credativ.de>
Mon, 23 Mar 2015 15:19:16 +0000 (16:19 +0100)
action=sequence used to open a new session for every sequence checked,
which could be very slow. Fix by creating a single SQL statement using
UNION ALL to query all sequences at once.

check_postgres.pl
t/02_sequence.t
t/CP_Testing.pm

index 5f78bbb8c95ed92a2487f0a67d4662df516eb64d..fbffae2c30e159a81184df22ac924367498c51ab 100755 (executable)
@@ -7274,12 +7274,15 @@ ORDER BY nspname, seqname, typname
         my %seqinfo;
         my %seqperf;
         my $multidb = @{$info->{db}} > 1 ? "$db->{dbname}." : '';
-        for my $r (@{$db->{slurp}}) {
+        my @seq_sql;
+        for my $r (@{$db->{slurp}}) { # for each sequence, create SQL command to inspect it
             my ($schema, $seq, $seqname, $typename) = @$r{qw/ nspname seqname safename typname /};
             next if skip_item($seq);
             my $maxValue = $typename eq 'int2' ? $MAXINT2 : $typename eq 'int4' ? $MAXINT4 : $MAXINT8;
-            $SQL = qq{
-SELECT last_value, slots, used, ROUND(used/slots*100) AS percent,
+            my $seqname_l = $seqname;
+            $seqname_l =~ s/'/''/g; # SQL literal quoting (name is already identifier-quoted)
+            push @seq_sql, qq{
+SELECT '$seqname_l' AS seqname, last_value, slots, used, ROUND(used/slots*100) AS percent,
   CASE WHEN slots < used THEN 0 ELSE slots - used END AS numleft
 FROM (
  SELECT last_value,
@@ -7287,10 +7290,10 @@ FROM (
   CEIL((last_value-min_value::numeric+1)/increment_by::NUMERIC) AS used
 FROM $seqname) foo
 };
-
-            my $seqinfo = run_command($SQL, { target => $db });
-            my $r2 = $seqinfo->{db}[0]{slurp}[0];
-            my ($last, $slots, $used, $percent, $left) = @$r2{qw/ last_value slots used percent numleft / };
+        }
+        my $seqinfo = run_command(join("\nUNION ALL\n", @seq_sql), { target => $db }); # execute all SQL commands at once
+        for my $r2 (@{$seqinfo->{db}[0]{slurp}}) { # now look at all results
+            my ($seqname, $last, $slots, $used, $percent, $left) = @$r2{qw/ seqname last_value slots used percent numleft / };
             if (! defined $last) {
                 ndie msg('seq-die', $seqname);
             }
@@ -9825,6 +9828,8 @@ Items not specifically attributed are by GSM (Greg Sabino Mullane).
 
   Declare POD encoding to be utf8. (Christoph Berg)
 
+  Query all sequences per DB in parallel for action=sequence. (Christoph Berg)
+
 =item B<Version 2.21.0> September 24, 2013
 
   Fix issue with SQL steps in check_pgagent_jobs for sql steps which perform deletes
index d42187f61452dfcebf7f5d227bdec6eff98f4d62..b1fa3ea31b880bdabbc22bdc2de398011b5040dc 100644 (file)
@@ -6,7 +6,7 @@ use 5.006;
 use strict;
 use warnings;
 use Data::Dumper;
-use Test::More tests => 10;
+use Test::More tests => 12;
 use lib 't','.';
 use CP_Testing;
 
@@ -45,6 +45,7 @@ if ($ver < 80100) {
 my $seqname = 'cp_test_sequence';
 $cp->drop_sequence_if_exists($seqname);
 $cp->drop_sequence_if_exists("${seqname}2");
+$cp->drop_sequence_if_exists("${seqname}'\"evil");
 
 $t=qq{$S works when no sequences exist};
 like ($cp->run(''), qr{OK:.+No sequences found}, $t);
@@ -83,4 +84,16 @@ like ($cp->run('--critical=22%'), qr{CRITICAL:.+public.cp_test_sequence=33% \(ca
 $t=qq{$S returns correct information with MRTG output};
 is ($cp->run('--critical=22% --output=mrtg'), "33\n0\n\npublic.cp_test_sequence\n", $t);
 
+# create second sequence
+$dbh->do("CREATE SEQUENCE ${seqname}2");
+$dbh->commit();
+$t=qq{$S returns correct information for two sequences};
+like ($cp->run(''), qr{OK:.+public.cp_test_sequence=33% .* \| .*${seqname}=33%.*${seqname}2=0%}, $t);
+
+# test SQL quoting
+$dbh->do(qq{CREATE SEQUENCE "${seqname}'""evil"});
+$dbh->commit();
+$t=qq{$S handles SQL quoting};
+like ($cp->run(''), qr{OK:.+'public."${seqname}''""evil"'}, $t); # extra " and ' because name is both identifier+literal quoted
+
 exit;
index 28ff60b3f6e08f9c6bb096b3cceacebc2510a8cb..c473c9f75a6d92d3ca7e9a57badfb557ce96b5b7 100644 (file)
@@ -700,7 +700,8 @@ sub drop_sequence_if_exists {
     $SQL = q{SELECT count(*) FROM pg_class WHERE relkind = 'S' AND relname = } . $dbh->quote($name);
     my $count = $dbh->selectall_arrayref($SQL)->[0][0];
     if ($count) {
-        $dbh->do("DROP SEQUENCE $name");
+        $name =~ s/"/""/g;
+        $dbh->do("DROP SEQUENCE \"$name\"");
         $dbh->commit();
     }
     return;