Changed all tabs to spaces, by popular demand.
authorGreg Sabino Mullane <[email protected]>
Wed, 7 Apr 2010 18:48:16 +0000 (14:48 -0400)
committerGreg Sabino Mullane <[email protected]>
Wed, 7 Apr 2010 18:48:16 +0000 (14:48 -0400)
check_postgres.pl

index eafdea1aab02aee285a3db1eb4552739a5bdb9d1..87f5cd9feb9a55fa3095c72c0fb18e904419aa60 100755 (executable)
@@ -67,12 +67,12 @@ our $YELLNAME = 1;
 ## Preferred order of ways to fetch pages for new_version checks
 our $get_method_timeout = 30;
 our @get_methods = (
-       "GET -t $get_method_timeout",
-       "wget --quiet --timeout=$get_method_timeout -O -",
-       "fetch -q -T $get_method_timeout -o -",
-       "curl --silent --max-time=$get_method_timeout",
-       "lynx --connect-timeout=$get_method_timeout --dump",
-       'links -dump',
+    "GET -t $get_method_timeout",
+    "wget --quiet --timeout=$get_method_timeout -O -",
+    "fetch -q -T $get_method_timeout -o -",
+    "curl --silent --max-time=$get_method_timeout",
+    "lynx --connect-timeout=$get_method_timeout --dump",
+    'links -dump',
 );
 
 ## Nothing below this line should need to be changed for normal usage.
@@ -85,504 +85,504 @@ our @get_methods = (
 ## no critic (RequireInterpolationOfMetachars)
 our %msg = (
 'en' => {
-       'address'            => q{address},
-       'backends-fatal'     => q{Could not connect: too many connections},
-       'backends-mrtg'      => q{DB=$1 Max connections=$2},
-       'backends-msg'       => q{$1 of $2 connections ($3%)},
-       'backends-nomax'     => q{Could not determine max_connections},
-       'backends-oknone'    => q{No connections},
-       'backends-po'        => q{sorry, too many clients already},
-       'backends-users'     => q{$1 for number of users must be a number or percentage},
-       'bloat-index'        => q{(db $1) index $2 rows:$3 pages:$4 shouldbe:$5 ($6X) wasted bytes:$7 ($8)},
-       'bloat-nomin'        => q{no relations meet the minimum bloat criteria},
-       'bloat-table'        => q{(db $1) table $2.$3 rows:$4 pages:$5 shouldbe:$6 ($7X) wasted size:$8 ($9)},
-       'checkpoint-baddir'  => q{Invalid data_directory: "$1"},
-       'checkpoint-baddir2' => q{pg_controldata could not read the given data directory: "$1"},
-       'checkpoint-badver'  => q{Failed to run pg_controldata - probably the wrong version},
-       'checkpoint-badver2' => q{Failed to run pg_controldata - is it the correct version?},
-       'checkpoint-nodir'   => q{Must supply a --datadir argument or set the PGDATA environment variable},
-       'checkpoint-nodp'    => q{Must install the Perl module Date::Parse to use the checkpoint action},
-       'checkpoint-noparse' => q{Unable to parse pg_controldata output: "$1"},
-       'checkpoint-noregex' => q{Call to pg_controldata $1 failed},
-       'checkpoint-nosys'   => q{Could not call pg_controldata: $1},
-       'checkpoint-ok'      => q{Last checkpoint was 1 second ago},
-       'checkpoint-ok2'     => q{Last checkpoint was $1 seconds ago},
-       'checkpoint-po'      => q{Time of latest checkpoint:},
-       'checksum-badline'   => q{Invalid pg_setting line: $1},
-       'checksum-msg'       => q{checksum: $1},
-       'checksum-nomd'      => q{Must install the Perl module Digest::MD5 to use the checksum action},
-       'checksum-nomrtg'    => q{Must provide a checksum via the --mrtg option},
-       'custom-invalid'     => q{Invalid format returned by custom query},
-       'custom-norows'      => q{No rows returned},
-       'custom-nostring'    => q{Must provide a query string},
-       'database'           => q{database},
-       'dbsize-version'     => q{Target database must be version 8.1 or higher to run the database_size action},
-       'die-action-version' => q{Cannot run "$1": server version must be >= $2, but is $3},
-       'die-badtime'        => q{Value for '$1' must be a valid time. Examples: -$2 1s  -$2 "10 minutes"},
-       'die-badversion'     => q{Invalid version string: $1},
-       'die-noset'          => q{Cannot run "$1" $2 is not set to on},
-       'die-nosetting'      => q{Could not fetch setting '$1'},
-       'diskspace-fail'     => q{Invalid result from command "$1": $2},
-       'diskspace-msg'      => q{FS $1 mounted on $2 is using $3 of $4 ($5%)},
-       'diskspace-nodata'   => q{Could not determine data_directory: are you connecting as a superuser?},
-       'diskspace-nodf'     => q{Could not find required executable /bin/df},
-       'diskspace-nodir'    => q{Could not find data directory "$1"},
-       'file-noclose'       => q{Could not close $1: $2},
-       'fsm-page-highver'   => q{Cannot check on fsm_pages on servers version 8.4 or greater},
-       'fsm-page-msg'       => q{fsm page slots used: $1 of $2 ($3%)},
-       'fsm-rel-highver'    => q{Cannot check on fsm_relations on servers version 8.4 or greater},
-       'fsm-rel-msg'        => q{fsm relations used: $1 of $2 ($3%)},
-       'invalid-option'     => q{Invalid option},
-       'invalid-query'      => q{Invalid query returned: $1},
-       'listener-count'     => q{ listening=$1}, ## needs leading space
-       'listener-msg'       => q{listeners found: $1},
-       'locks-msg'          => q{total "$1" locks: $2},
-       'locks-msg2'         => q{total locks: $1},
-       'logfile-bad'        => q{Invalid logfile "$1"},
-       'logfile-debug'      => q{Dest is $1, dir is $2, file is $3, facility is $4},
-       'logfile-debug2'     => q{Final logfile: $1},
-       'logfile-dne'        => q{logfile $1 does not exist!},
-       'logfile-fail'       => q{fails logging to: $1},
-       'logfile-ok'         => q{logs to: $1},
-       'logfile-openfail'   => q{logfile "$1" failed to open: $2},
-       'logfile-opt-bad'    => q{Invalid logfile option},
-       'logfile-seekfail'   => q{Seek on $1 failed: $2},
-       'logfile-stderr'     => q{Logfile output has been redirected to stderr: please provide a filename},
-       'logfile-syslog'     => q{Database is using syslog, please specify path with --logfile option (fac=$1)},
-       'maxtime'            => q{ maxtime=$1}, ## needs leading space
-       'mrtg-fail'          => q{Action $1 failed: $2},
-       'new-bc-badver'      => q{Could not determine the version of Bucardo},
-       'new-bc-fail'        => q{Could not find current version information for Bucardo},
-       'new-bc-ok'          => q{Version $1 is the latest for Bucardo},
-       'new-bc-warn'        => q{Please upgrade to version $1 of Bucardo. You are running $2},
-       'new-cp-fail'        => q{Unable to determine the current version of check_postgres.pl},
-       'new-cp-ok'          => q{Version $1 is the latest for check_postgres.pl},
-       'new-cp-warn'        => q{Version $1 of check_postgres.pl exists (this is version $2)},
-       'new-pg-badver'      => q{Could not determine the Postgres revision (version was $1)},
-       'new-pg-badver2'     => q{Could not find revision information for Postgres version $1},
-       'new-pg-big'         => q{Please upgrade to version $1 of Postgres. You are running $2},
-       'new-pg-match'       => q{Postgres is at the latest revision ($1)},
-       'new-pg-small'       => q{The latest version of Postgres is $1, but you are running $2?},
-       'no-match-db'        => q{No matching databases found due to exclusion/inclusion options},
-       'no-match-fs'        => q{No matching file systems found due to exclusion/inclusion options},
-       'no-match-rel'       => q{No matching relations found due to exclusion/inclusion options},
-       'no-match-set'       => q{No matching settings found due to exclusion/inclusion options},
-       'no-match-table'     => q{No matching tables found due to exclusion/inclusion options},
-       'no-match-user'      => q{No matching entries found due to user exclusion/inclusion options},
-       'no-time-hires'      => q{Cannot find Time::HiRes, needed if 'showtime' is true},
-       'opt-output-invalid' => q{Invalid output: must be 'nagios' or 'mrtg' or 'simple' or 'cacti'},
-       'opt-psql-badpath'   => q{Invalid psql argument: must be full path to a file named psql},
-       'opt-psql-noexec'    => q{The file "$1" does not appear to be executable},
-       'opt-psql-noexist'   => q{Cannot find given psql executable: $1},
-       'opt-psql-nofind'    => q{Could not find a suitable psql executable},
-       'opt-psql-nover'     => q{Could not determine psql version},
-       'opt-psql-restrict'  => q{Cannot use the --PSQL option when NO_PSQL_OPTION is on},
-       'PID'                => q{PID},
-       'port'               => q{port},
-       'preptxn-none'       => q{No prepared transactions found},
-       'psa-nomatches'      => q{No queries were found},
-       'psa-nosuper'        => q{No matches - please run as a superuser},
-       'psa-skipped'        => q{No matching rows were found (skipped rows: $1)},
-       'qtime-fail'         => q{Cannot run the txn_idle action unless stats_command_string is set to 'on'!},
-       'qtime-msg'          => q{longest query: $1s},
-       'qtime-nomatch'      => q{No queries were found},
-       'Query'              => q{Query: $1},
-       'range-badcs'        => q{Invalid '$1' option: must be a checksum},
-       'range-badlock'      => q{Invalid '$1' option: must be number of locks, or "type1=#;type2=#"},
-       'range-badpercent'   => q{Invalid '$1' option: must be a percentage},
-       'range-badpercsize'  => q{Invalid '$1' option: must be a size or a percentage},
-       'range-badsize'      => q{Invalid size for '$1' option},
-       'range-badtype'      => q{validate_range called with unknown type '$1'},
-       'range-badversion'   => q{Invalid string for '$1' option: $2},
-       'range-cactionly'    => q{This action is for cacti use only and takes no warning or critical arguments},
-       'range-int'          => q{Invalid argument for '$1' option: must be an integer},
-       'range-int-pos'      => q{Invalid argument for '$1' option: must be a positive integer},
-       'range-neg-percent'  => q{Cannot specify a negative percent!},
-       'range-none'         => q{No warning or critical options are needed},
-       'range-noopt-both'   => q{Must provide both 'warning' and 'critical' options},
-       'range-noopt-one'    => q{Must provide a 'warning' or 'critical' option},
-       'range-noopt-only'   => q{Can only provide 'warning' OR 'critical' option},
-       'range-noopt-orboth' => q{Must provide a 'warning' option, a 'critical' option, or both},
-       'range-noopt-size'   => q{Must provide a warning and/or critical size},
-       'range-nosize'       => q{Must provide a warning and/or critical size},
-       'range-notime'       => q{Must provide a warning and/or critical time},
-       'range-seconds'      => q{Invalid argument to '$1' option: must be number of seconds},
-       'range-version'      => q{must be in the format X.Y or X.Y.Z, where X is the major version number, },
-       'range-warnbig'      => q{The 'warning' option cannot be greater than the 'critical' option},
-       'range-warnbigsize'  => q{The 'warning' option ($1 bytes) cannot be larger than the 'critical' option ($2 bytes)},
-       'range-warnbigtime'  => q{The 'warning' option ($1 s) cannot be larger than the 'critical' option ($2 s)},
-       'range-warnsmall'    => q{The 'warning' option cannot be less than the 'critical' option},
-       'relsize-msg-ind'    => q{largest index is "$1": $2},
-       'relsize-msg-reli'   => q{largest relation is index "$1": $2},
-       'relsize-msg-relt'   => q{largest relation is table "$1": $2},
-       'relsize-msg-tab'    => q{largest table is "$1": $2},
-       'rep-badarg'         => q{Invalid repinfo argument: expected 6 comma-separated values},
-       'rep-duh'            => q{Makes no sense to test replication with same values},
-       'rep-fail'           => q{Row not replicated to slave $1},
-       'rep-noarg'          => q{Need a repinfo argument},
-       'rep-norow'          => q{Replication source row not found: $1},
-       'rep-noslaves'       => q{No slaves found},
-       'rep-notsame'        => q{Cannot test replication: values are not the same},
-       'rep-ok'             => q{Row was replicated},
-       'rep-sourcefail'     => q{Source update failed},
-       'rep-timeout'        => q{Row was not replicated. Timeout: $1},
-       'rep-unknown'        => q{Replication check failed},
-       'rep-wrongvals'      => q{Cannot test replication: values are not the right ones ($1 not $2 nor $3)},
-       'runcommand-err'     => q{Unknown error inside of the "run_command" function},
-       'runcommand-nodb'    => q{No target databases could be found},
-       'runcommand-nodupe'  => q{Could not dupe STDERR},
-       'runcommand-noerr'   => q{Could not open STDERR?!},
-       'runcommand-nosys'   => q{System call failed with a $1},
-       'runcommand-pgpass'  => q{Created temporary pgpass file $1},
-       'runcommand-timeout' => q{Command timed out! Consider boosting --timeout higher than $1},
-       'runtime-badmrtg'    => q{invalid queryname?},
-       'runtime-badname'    => q{Invalid queryname option: must be a simple view name},
-       'runtime-msg'        => q{query runtime: $1 seconds},
-       'same-failed'        => q{Databases were different. Items not matched: $1},
-       'same-matched'       => q{Both databases have identical items},
-       'seq-die'            => q{Could not determine information about sequence $1},
-       'seq-msg'            => q{$1=$2% (calls left=$3)},
-       'seq-none'           => q{No sequences found},
-       'slony-noschema'     => q{Could not determine the schema for Slony},
-       'slony-nonumber'     => q{Call to sl_status did not return a number},
-       'slony-noparse'      => q{Could not parse call to sl_status},
-       'slony-lagtime'      => q{Slony lag time: $1},
-       'symlink-create'     => q{Created "$1"},
-       'symlink-done'       => q{Not creating "$1": $2 already linked to "$3"},
-       'symlink-exists'     => q{Not creating "$1": $2 file already exists},
-       'symlink-fail1'      => q{Failed to unlink "$1": $2},
-       'symlink-fail2'      => q{Could not symlink $1 to $2: $3},
-       'symlink-name'       => q{This command will not work unless the program has the word "postgres" in it},
-       'symlink-unlink'     => q{Unlinking "$1":$2 },
-       'testmode-end'       => q{END OF TEST MODE},
-       'testmode-fail'      => q{Connection failed: $1 $2},
-       'testmode-norun'     => q{Cannot run "$1" on $2: version must be >= $3, but is $4},
-       'testmode-noset'     => q{Cannot run "$1" on $2: $3 is not set to on},
-       'testmode-nover'     => q{Could not find version for $1},
-       'testmode-ok'        => q{Connection ok: $1},
-       'testmode-start'     => q{BEGIN TEST MODE},
-       'time-day'           => q{day},
-       'time-days'          => q{days},
-       'time-hour'          => q{hour},
-       'time-hours'         => q{hours},
-       'time-minute'        => q{minute},
-       'time-minutes'       => q{minutes},
-       'time-month'         => q{month},
-       'time-months'        => q{months},
-       'time-second'        => q{second},
-       'time-seconds'       => q{seconds},
-       'time-week'          => q{week},
-       'time-weeks'         => q{weeks},
-       'time-year'          => q{year},
-       'time-years'         => q{years},
-       'timesync-diff'      => q{ diff=$1}, ## needs leading space
-       'timesync-msg'       => q{timediff=$1 DB=$2 Local=$3},
-       'trigger-msg'        => q{Disabled triggers: $1},
-       'txnidle-msg'        => q{longest idle in txn: $1s},
-       'txnidle-none'       => q{no idle in transaction},
-       'txntime-fail'       => q{Query failed},
-       'txntime-msg'        => q{longest txn: $1s},
-       'txntime-none'       => q{No transactions},
-       'txnwrap-cbig'       => q{The 'critical' value must be less than 2 billion},
-       'txnwrap-wbig'       => q{The 'warning' value must be less than 2 billion},
-       'unknown-error'      => q{Unknown error},
-       'usage'              => qq{\nUsage: \$1 <options>\n Try "\$1 --help" for a complete list of options\n Try "\$1 --man" for the full manual\n},
-       'username'           => q{username},
-       'vac-msg'            => q{DB: $1 TABLE: $2},
-       'vac-nomatch-a'      => q{No matching tables have ever been analyzed},
-       'vac-nomatch-v'      => q{No matching tables have ever been vacuumed},
-       'version'            => q{version $1},
-       'version-badmrtg'    => q{Invalid mrtg version argument},
-       'version-fail'       => q{version $1, but expected $2},
-       'version-ok'         => q{version $1},
+    'address'            => q{address},
+    'backends-fatal'     => q{Could not connect: too many connections},
+    'backends-mrtg'      => q{DB=$1 Max connections=$2},
+    'backends-msg'       => q{$1 of $2 connections ($3%)},
+    'backends-nomax'     => q{Could not determine max_connections},
+    'backends-oknone'    => q{No connections},
+    'backends-po'        => q{sorry, too many clients already},
+    'backends-users'     => q{$1 for number of users must be a number or percentage},
+    'bloat-index'        => q{(db $1) index $2 rows:$3 pages:$4 shouldbe:$5 ($6X) wasted bytes:$7 ($8)},
+    'bloat-nomin'        => q{no relations meet the minimum bloat criteria},
+    'bloat-table'        => q{(db $1) table $2.$3 rows:$4 pages:$5 shouldbe:$6 ($7X) wasted size:$8 ($9)},
+    'checkpoint-baddir'  => q{Invalid data_directory: "$1"},
+    'checkpoint-baddir2' => q{pg_controldata could not read the given data directory: "$1"},
+    'checkpoint-badver'  => q{Failed to run pg_controldata - probably the wrong version},
+    'checkpoint-badver2' => q{Failed to run pg_controldata - is it the correct version?},
+    'checkpoint-nodir'   => q{Must supply a --datadir argument or set the PGDATA environment variable},
+    'checkpoint-nodp'    => q{Must install the Perl module Date::Parse to use the checkpoint action},
+    'checkpoint-noparse' => q{Unable to parse pg_controldata output: "$1"},
+    'checkpoint-noregex' => q{Call to pg_controldata $1 failed},
+    'checkpoint-nosys'   => q{Could not call pg_controldata: $1},
+    'checkpoint-ok'      => q{Last checkpoint was 1 second ago},
+    'checkpoint-ok2'     => q{Last checkpoint was $1 seconds ago},
+    'checkpoint-po'      => q{Time of latest checkpoint:},
+    'checksum-badline'   => q{Invalid pg_setting line: $1},
+    'checksum-msg'       => q{checksum: $1},
+    'checksum-nomd'      => q{Must install the Perl module Digest::MD5 to use the checksum action},
+    'checksum-nomrtg'    => q{Must provide a checksum via the --mrtg option},
+    'custom-invalid'     => q{Invalid format returned by custom query},
+    'custom-norows'      => q{No rows returned},
+    'custom-nostring'    => q{Must provide a query string},
+    'database'           => q{database},
+    'dbsize-version'     => q{Target database must be version 8.1 or higher to run the database_size action},
+    'die-action-version' => q{Cannot run "$1": server version must be >= $2, but is $3},
+    'die-badtime'        => q{Value for '$1' must be a valid time. Examples: -$2 1s  -$2 "10 minutes"},
+    'die-badversion'     => q{Invalid version string: $1},
+    'die-noset'          => q{Cannot run "$1" $2 is not set to on},
+    'die-nosetting'      => q{Could not fetch setting '$1'},
+    'diskspace-fail'     => q{Invalid result from command "$1": $2},
+    'diskspace-msg'      => q{FS $1 mounted on $2 is using $3 of $4 ($5%)},
+    'diskspace-nodata'   => q{Could not determine data_directory: are you connecting as a superuser?},
+    'diskspace-nodf'     => q{Could not find required executable /bin/df},
+    'diskspace-nodir'    => q{Could not find data directory "$1"},
+    'file-noclose'       => q{Could not close $1: $2},
+    'fsm-page-highver'   => q{Cannot check on fsm_pages on servers version 8.4 or greater},
+    'fsm-page-msg'       => q{fsm page slots used: $1 of $2 ($3%)},
+    'fsm-rel-highver'    => q{Cannot check on fsm_relations on servers version 8.4 or greater},
+    'fsm-rel-msg'        => q{fsm relations used: $1 of $2 ($3%)},
+    'invalid-option'     => q{Invalid option},
+    'invalid-query'      => q{Invalid query returned: $1},
+    'listener-count'     => q{ listening=$1}, ## needs leading space
+    'listener-msg'       => q{listeners found: $1},
+    'locks-msg'          => q{total "$1" locks: $2},
+    'locks-msg2'         => q{total locks: $1},
+    'logfile-bad'        => q{Invalid logfile "$1"},
+    'logfile-debug'      => q{Dest is $1, dir is $2, file is $3, facility is $4},
+    'logfile-debug2'     => q{Final logfile: $1},
+    'logfile-dne'        => q{logfile $1 does not exist!},
+    'logfile-fail'       => q{fails logging to: $1},
+    'logfile-ok'         => q{logs to: $1},
+    'logfile-openfail'   => q{logfile "$1" failed to open: $2},
+    'logfile-opt-bad'    => q{Invalid logfile option},
+    'logfile-seekfail'   => q{Seek on $1 failed: $2},
+    'logfile-stderr'     => q{Logfile output has been redirected to stderr: please provide a filename},
+    'logfile-syslog'     => q{Database is using syslog, please specify path with --logfile option (fac=$1)},
+    'maxtime'            => q{ maxtime=$1}, ## needs leading space
+    'mrtg-fail'          => q{Action $1 failed: $2},
+    'new-bc-badver'      => q{Could not determine the version of Bucardo},
+    'new-bc-fail'        => q{Could not find current version information for Bucardo},
+    'new-bc-ok'          => q{Version $1 is the latest for Bucardo},
+    'new-bc-warn'        => q{Please upgrade to version $1 of Bucardo. You are running $2},
+    'new-cp-fail'        => q{Unable to determine the current version of check_postgres.pl},
+    'new-cp-ok'          => q{Version $1 is the latest for check_postgres.pl},
+    'new-cp-warn'        => q{Version $1 of check_postgres.pl exists (this is version $2)},
+    'new-pg-badver'      => q{Could not determine the Postgres revision (version was $1)},
+    'new-pg-badver2'     => q{Could not find revision information for Postgres version $1},
+    'new-pg-big'         => q{Please upgrade to version $1 of Postgres. You are running $2},
+    'new-pg-match'       => q{Postgres is at the latest revision ($1)},
+    'new-pg-small'       => q{The latest version of Postgres is $1, but you are running $2?},
+    'no-match-db'        => q{No matching databases found due to exclusion/inclusion options},
+    'no-match-fs'        => q{No matching file systems found due to exclusion/inclusion options},
+    'no-match-rel'       => q{No matching relations found due to exclusion/inclusion options},
+    'no-match-set'       => q{No matching settings found due to exclusion/inclusion options},
+    'no-match-table'     => q{No matching tables found due to exclusion/inclusion options},
+    'no-match-user'      => q{No matching entries found due to user exclusion/inclusion options},
+    'no-time-hires'      => q{Cannot find Time::HiRes, needed if 'showtime' is true},
+    'opt-output-invalid' => q{Invalid output: must be 'nagios' or 'mrtg' or 'simple' or 'cacti'},
+    'opt-psql-badpath'   => q{Invalid psql argument: must be full path to a file named psql},
+    'opt-psql-noexec'    => q{The file "$1" does not appear to be executable},
+    'opt-psql-noexist'   => q{Cannot find given psql executable: $1},
+    'opt-psql-nofind'    => q{Could not find a suitable psql executable},
+    'opt-psql-nover'     => q{Could not determine psql version},
+    'opt-psql-restrict'  => q{Cannot use the --PSQL option when NO_PSQL_OPTION is on},
+    'PID'                => q{PID},
+    'port'               => q{port},
+    'preptxn-none'       => q{No prepared transactions found},
+    'psa-nomatches'      => q{No queries were found},
+    'psa-nosuper'        => q{No matches - please run as a superuser},
+    'psa-skipped'        => q{No matching rows were found (skipped rows: $1)},
+    'qtime-fail'         => q{Cannot run the txn_idle action unless stats_command_string is set to 'on'!},
+    'qtime-msg'          => q{longest query: $1s},
+    'qtime-nomatch'      => q{No queries were found},
+    'Query'              => q{Query: $1},
+    'range-badcs'        => q{Invalid '$1' option: must be a checksum},
+    'range-badlock'      => q{Invalid '$1' option: must be number of locks, or "type1=#;type2=#"},
+    'range-badpercent'   => q{Invalid '$1' option: must be a percentage},
+    'range-badpercsize'  => q{Invalid '$1' option: must be a size or a percentage},
+    'range-badsize'      => q{Invalid size for '$1' option},
+    'range-badtype'      => q{validate_range called with unknown type '$1'},
+    'range-badversion'   => q{Invalid string for '$1' option: $2},
+    'range-cactionly'    => q{This action is for cacti use only and takes no warning or critical arguments},
+    'range-int'          => q{Invalid argument for '$1' option: must be an integer},
+    'range-int-pos'      => q{Invalid argument for '$1' option: must be a positive integer},
+    'range-neg-percent'  => q{Cannot specify a negative percent!},
+    'range-none'         => q{No warning or critical options are needed},
+    'range-noopt-both'   => q{Must provide both 'warning' and 'critical' options},
+    'range-noopt-one'    => q{Must provide a 'warning' or 'critical' option},
+    'range-noopt-only'   => q{Can only provide 'warning' OR 'critical' option},
+    'range-noopt-orboth' => q{Must provide a 'warning' option, a 'critical' option, or both},
+    'range-noopt-size'   => q{Must provide a warning and/or critical size},
+    'range-nosize'       => q{Must provide a warning and/or critical size},
+    'range-notime'       => q{Must provide a warning and/or critical time},
+    'range-seconds'      => q{Invalid argument to '$1' option: must be number of seconds},
+    'range-version'      => q{must be in the format X.Y or X.Y.Z, where X is the major version number, },
+    'range-warnbig'      => q{The 'warning' option cannot be greater than the 'critical' option},
+    'range-warnbigsize'  => q{The 'warning' option ($1 bytes) cannot be larger than the 'critical' option ($2 bytes)},
+    'range-warnbigtime'  => q{The 'warning' option ($1 s) cannot be larger than the 'critical' option ($2 s)},
+    'range-warnsmall'    => q{The 'warning' option cannot be less than the 'critical' option},
+    'relsize-msg-ind'    => q{largest index is "$1": $2},
+    'relsize-msg-reli'   => q{largest relation is index "$1": $2},
+    'relsize-msg-relt'   => q{largest relation is table "$1": $2},
+    'relsize-msg-tab'    => q{largest table is "$1": $2},
+    'rep-badarg'         => q{Invalid repinfo argument: expected 6 comma-separated values},
+    'rep-duh'            => q{Makes no sense to test replication with same values},
+    'rep-fail'           => q{Row not replicated to slave $1},
+    'rep-noarg'          => q{Need a repinfo argument},
+    'rep-norow'          => q{Replication source row not found: $1},
+    'rep-noslaves'       => q{No slaves found},
+    'rep-notsame'        => q{Cannot test replication: values are not the same},
+    'rep-ok'             => q{Row was replicated},
+    'rep-sourcefail'     => q{Source update failed},
+    'rep-timeout'        => q{Row was not replicated. Timeout: $1},
+    'rep-unknown'        => q{Replication check failed},
+    'rep-wrongvals'      => q{Cannot test replication: values are not the right ones ($1 not $2 nor $3)},
+    'runcommand-err'     => q{Unknown error inside of the "run_command" function},
+    'runcommand-nodb'    => q{No target databases could be found},
+    'runcommand-nodupe'  => q{Could not dupe STDERR},
+    'runcommand-noerr'   => q{Could not open STDERR?!},
+    'runcommand-nosys'   => q{System call failed with a $1},
+    'runcommand-pgpass'  => q{Created temporary pgpass file $1},
+    'runcommand-timeout' => q{Command timed out! Consider boosting --timeout higher than $1},
+    'runtime-badmrtg'    => q{invalid queryname?},
+    'runtime-badname'    => q{Invalid queryname option: must be a simple view name},
+    'runtime-msg'        => q{query runtime: $1 seconds},
+    'same-failed'        => q{Databases were different. Items not matched: $1},
+    'same-matched'       => q{Both databases have identical items},
+    'seq-die'            => q{Could not determine information about sequence $1},
+    'seq-msg'            => q{$1=$2% (calls left=$3)},
+    'seq-none'           => q{No sequences found},
+    'slony-noschema'     => q{Could not determine the schema for Slony},
+    'slony-nonumber'     => q{Call to sl_status did not return a number},
+    'slony-noparse'      => q{Could not parse call to sl_status},
+    'slony-lagtime'      => q{Slony lag time: $1},
+    'symlink-create'     => q{Created "$1"},
+    'symlink-done'       => q{Not creating "$1": $2 already linked to "$3"},
+    'symlink-exists'     => q{Not creating "$1": $2 file already exists},
+    'symlink-fail1'      => q{Failed to unlink "$1": $2},
+    'symlink-fail2'      => q{Could not symlink $1 to $2: $3},
+    'symlink-name'       => q{This command will not work unless the program has the word "postgres" in it},
+    'symlink-unlink'     => q{Unlinking "$1":$2 },
+    'testmode-end'       => q{END OF TEST MODE},
+    'testmode-fail'      => q{Connection failed: $1 $2},
+    'testmode-norun'     => q{Cannot run "$1" on $2: version must be >= $3, but is $4},
+    'testmode-noset'     => q{Cannot run "$1" on $2: $3 is not set to on},
+    'testmode-nover'     => q{Could not find version for $1},
+    'testmode-ok'        => q{Connection ok: $1},
+    'testmode-start'     => q{BEGIN TEST MODE},
+    'time-day'           => q{day},
+    'time-days'          => q{days},
+    'time-hour'          => q{hour},
+    'time-hours'         => q{hours},
+    'time-minute'        => q{minute},
+    'time-minutes'       => q{minutes},
+    'time-month'         => q{month},
+    'time-months'        => q{months},
+    'time-second'        => q{second},
+    'time-seconds'       => q{seconds},
+    'time-week'          => q{week},
+    'time-weeks'         => q{weeks},
+    'time-year'          => q{year},
+    'time-years'         => q{years},
+    'timesync-diff'      => q{ diff=$1}, ## needs leading space
+    'timesync-msg'       => q{timediff=$1 DB=$2 Local=$3},
+    'trigger-msg'        => q{Disabled triggers: $1},
+    'txnidle-msg'        => q{longest idle in txn: $1s},
+    'txnidle-none'       => q{no idle in transaction},
+    'txntime-fail'       => q{Query failed},
+    'txntime-msg'        => q{longest txn: $1s},
+    'txntime-none'       => q{No transactions},
+    'txnwrap-cbig'       => q{The 'critical' value must be less than 2 billion},
+    'txnwrap-wbig'       => q{The 'warning' value must be less than 2 billion},
+    'unknown-error'      => q{Unknown error},
+    'usage'              => qq{\nUsage: \$1 <options>\n Try "\$1 --help" for a complete list of options\n Try "\$1 --man" for the full manual\n},
+    'username'           => q{username},
+    'vac-msg'            => q{DB: $1 TABLE: $2},
+    'vac-nomatch-a'      => q{No matching tables have ever been analyzed},
+    'vac-nomatch-v'      => q{No matching tables have ever been vacuumed},
+    'version'            => q{version $1},
+    'version-badmrtg'    => q{Invalid mrtg version argument},
+    'version-fail'       => q{version $1, but expected $2},
+    'version-ok'         => q{version $1},
 },
 'fr' => {
-       'address'            => q{adresse},
-       'backends-fatal'     => q{N'a pas pu se connecter : trop de connexions},
-       'backends-mrtg'      => q{DB=$1 Connexions maximum=$2},
-       'backends-msg'       => q{$1 connexions sur $2 ($3%)},
-       'backends-nomax'     => q{N'a pas pu déterminer max_connections},
-       'backends-oknone'    => q{Aucune connexion},
-       'backends-po'        => q{désolé, trop de clients sont déjà connectés},
-       'backends-users'     => q{$1 pour le nombre d'utilisateurs doit être un nombre ou un pourcentage},
-       'bloat-index'        => q{(db $1) index $2 lignes:$3 pages:$4 devrait être:$5 ($6X) octets perdus:$7 ($8)},
-       'bloat-nomin'        => q{aucune relation n'atteint le critère minimum de fragmentation},
-       'bloat-table'        => q{(db $1) table $2.$3 lignes:$4 pages:$5 devrait être:$6 ($7X) place perdue:$8 ($9)},
-       'checkpoint-baddir'  => q{data_directory invalide : "$1"},
-       'checkpoint-baddir2' => q{pg_controldata n'a pas pu lire le répertoire des données indiqué : « $1 »},
-       'checkpoint-badver'  => q{Échec lors de l'exécution de pg_controldata - probablement la mauvaise version},
-       'checkpoint-badver2' => q{Échec lors de l'exécution de pg_controldata - est-ce la bonne version ?},
-       'checkpoint-nodir'   => q{Vous devez fournir un argument --datadir ou configurer la variable d'environnement PGDATA},
-       'checkpoint-nodp'    => q{Vous devez installer le module Perl Date::Parse pour utiliser l'action checkpoint},
-       'checkpoint-noparse' => q{Incapable d'analyser le résultat de la commande pg_controldata : "$1"},
-       'checkpoint-noregex' => q{Échec de l'appel à pg_controldata $1},
-       'checkpoint-nosys'   => q{N'a pas pu appeler pg_controldata : $1},
-       'checkpoint-ok'      => q{Le dernier CHECKPOINT est survenu il y a une seconde},
-       'checkpoint-ok2'     => q{Le dernier CHECKPOINT est survenu il y a $1 secondes},
-       'checkpoint-po'      => q{Heure du dernier point de contr�le :},
-       'checksum-badline'   => q{Ligne pg_setting invalide : $1},
-       'checksum-msg'       => q{somme de contrôle : $1},
-       'checksum-nomd'      => q{Vous devez installer le module Perl Digest::MD5 pour utiliser l'action checksum},
-       'checksum-nomrtg'    => q{Vous devez fournir une somme de contrôle avec l'option --mrtg},
-       'custom-invalid'     => q{Format invalide renvoyé par la requête personnalisée},
-       'custom-norows'      => q{Aucune ligne renvoyée},
-       'custom-nostring'    => q{Vous devez fournir une requête},
-       'database'           => q{base de données},
-       'dbsize-version'     => q{La base de données cible doit être une version 8.1 ou ultérieure pour exécuter l'action database_size},
-       'die-action-version' => q{Ne peut pas exécuter « $1 » : la version du serveur doit être supérieure ou égale à $2, alors qu'elle est $3},
-       'die-badtime'        => q{La valeur de « $1 » doit être une heure valide. Par exemple, -$2 1s  -$2 « 10 minutes »},
-       'die-badversion'     => q{Version invalide : $1},
-       'die-noset'          => q{Ne peut pas exécuter « $1 » $2 n'est pas activé},
-       'die-nosetting'      => q{N'a pas pu récupérer le paramètre « $1 »},
-       'diskspace-fail'     => q{Résultat invalide pour la commande « $1 » : $2},
-       'diskspace-msg'      => q{Le système de fichiers $1 monté sur $2 utilise $3 sur $4 ($5%)},
-       'diskspace-nodata'   => q{N'a pas pu déterminer data_directory : êtes-vous connecté en tant que super-utilisateur ?},
-       'diskspace-nodf'     => q{N'a pas pu trouver l'exécutable /bin/df},
-       'diskspace-nodir'    => q{N'a pas pu trouver le répertoire des données « $1 »},
-       'file-noclose'       => q{N'a pas pu fermer $1 : $2},
-       'fsm-page-highver'   => q{Ne peut pas vérifier fsm_pages sur des serveurs en version 8.4 ou ultérieure},
-       'fsm-page-msg'       => q{emplacements de pages utilisés par la FSM : $1 sur $2 ($3%)},
-       'fsm-rel-highver'    => q{Ne peut pas vérifier fsm_relations sur des serveurs en version 8.4 ou ultérieure},
-       'fsm-rel-msg'        => q{relations tracées par la FSM : $1 sur $2 ($3%)},
-       'invalid-option'     => q{Option invalide},
-       'invalid-query'      => q{Une requête invalide a renvoyé : $1},
-       'listener-count'     => q{ en écoute=$1}, ## needs leading space
-       'listener-msg'       => q{processus LISTEN trouvés : $1},
-       'locks-msg'          => q{total des verrous « $1 » : $2},
-       'locks-msg2'         => q{total des verrous : $1},
-       'logfile-bad'        => q{Option logfile invalide « $1 »},
-       'logfile-debug'      => q{la destination est $1, le répertoire est $2, le fichier est $3, l'option facility est $4},
-       'logfile-debug2'     => q{Journal applicatif final : $1},
-       'logfile-dne'        => q{le journal applicatif $1 n'existe pas !},
-       'logfile-fail'       => q{échec pour tracer dans : $1},
-       'logfile-ok'         => q{trace dans : $1},
-       'logfile-openfail'   => q{échec pour l'ouverture du journal applicatif « $1 » : $2},
-       'logfile-opt-bad'    => q{Option logfile invalide},
-       'logfile-seekfail'   => q{Échec de la recherche dans $1 : $2},
-       'logfile-stderr'     => q{La sortie des traces a été redirigés stderr : merci de fournir un nom de fichier},
-       'logfile-syslog'     => q{La base de données utiliser syslog, merci de spécifier le chemin avec l'option --logfile (fac=$1)},
-       'maxtime'            => q{ maxtime=$1}, ## needs leading space
-       'mrtg-fail'          => q{Échec de l'action $1 : $2},
-       'new-bc-badver'      => q{N'a pas pu déterminer la version de Bucardo},
-       'new-bc-fail'        => q{N'a pas pu trouver la version actuelle pour Bucardo},
-       'new-bc-ok'          => q{La version $1 est la dernière pour Bucardo},
-       'new-bc-warn'        => q{Merci de mettre à jour vers la version $1 de Bucardo. Vous utilisez actuellement la $2},
-       'new-cp-fail'        => q{Incapable de déterminer la version actuelle de check_postgres.pl},
-       'new-cp-ok'          => q{La version $1 est la dernière pour check_postgres.pl},
-       'new-cp-warn'        => q{La version $1 de check_postgres.pl existe (ceci est la version $2)},
-       'new-pg-badver'      => q{N'a pas pu déterminer la révision de Postgres (la version était $1)},
-       'new-pg-badver2'     => q{N'a pas pu trouver l'information de révision de Posrgres version $1},
-       'new-pg-big'         => q{Veuillez mettre à jour Postgres vers la version $1. Vous utilisez actuellement la version $2},
-       'new-pg-match'       => q{Postgres est à la dernière révision ($1)},
-       'new-pg-small'       => q{La dernière version de Postgres est la $1, mais vous utilisez actuellement la version $2?},
-       'no-match-db'        => q{Aucune base de données trouvée à cause des options d'exclusion/inclusion},
-       'no-match-fs'        => q{Aucun système de fichier trouvé à cause des options d'exclusion/inclusion},
-       'no-match-rel'       => q{Aucune relation trouvée à cause des options d'exclusion/inclusion},
-       'no-match-set'       => q{Aucun paramètre trouvé à cause des options d'exclusion/inclusion},
-       'no-match-table'     => q{Aucune table trouvée à cause des options d'exclusion/inclusion},
-       'no-match-user'      => q{Aucune entrée trouvée à cause options d'exclusion/inclusion},
-       'no-time-hires'      => q{N'a pas trouvé le module Time::HiRes, nécessaire quand « showtime » est activé},
-       'opt-output-invalid' => q{Sortie invalide : doit être 'nagios' ou 'mrtg' ou 'simple' ou 'cacti'},
-       'opt-psql-badpath'   => q{Argument invalide pour psql : doit être le chemin complet vers un fichier nommé psql},
-       'opt-psql-noexec'    => q{ Le fichier « $1 » ne paraît pas exécutable},
-       'opt-psql-noexist'   => q{Ne peut pas trouver l'exécutable psql indiqué : $1},
-       'opt-psql-nofind'    => q{N'a pas pu trouver un psql exécutable},
-       'opt-psql-nover'     => q{N'a pas pu déterminer la version de psql},
-       'opt-psql-restrict'  => q{Ne peut pas utiliser l'option --PSQL si NO_PSQL_OPTION est activé},
-       'PID'                => q{PID},
-       'port'               => q{port},
-       'preptxn-none'       => q{Aucune transaction préparée trouvée},
-       'qtime-fail'         => q{Ne peut pas exécuter l'action txn_idle si stats_command_string est désactivé !},
-       'qtime-msg'          => q{requête la plus longue : $1s},
-       'qtime-nomatch'      => q{Aucune entrée correspondante n'a été trouvée},
-       'range-badcs'        => q{Option « $1 » invalide : doit être une somme de contrôle},
-       'range-badlock'      => q{Option « $1 » invalide : doit être un nombre de verrou ou « type1=#;type2=# »},
-       'range-badpercent'   => q{Option « $1 » invalide : doit être un pourcentage},
-       'range-badpercsize'  => q{Option « $1 » invalide : doit être une taille ou un pourcentage},
-       'range-badsize'      => q{Taille invalide pour l'option « $1 »},
-       'range-badtype'      => q{validate_range appelé avec un type inconnu « $1 »},
-       'range-badversion'   => q{Chaîne invalide pour l'option « $1 » : $2},
-       'range-cactionly'    => q{Cette action est pour cacti seulement et ne prend pas les arguments warning et critical},
-       'range-int'          => q{Argument invalide pour l'option « $1 » : doit être un entier},
-       'range-int-pos'      => q{Argument invalide pour l'option « $1 » : doit être un entier positif},
-       'range-neg-percent'  => q{Ne peut pas indiquer un pourcentage négatif !},
-       'range-none'         => q{Les options warning et critical ne sont pas nécessaires},
-       'range-noopt-both'   => q{Doit fournir les options warning et critical},
-       'range-noopt-one'    => q{Doit fournir une option warning ou critical},
-       'range-noopt-only'   => q{Peut seulement fournir une option warning ou critical},
-       'range-noopt-orboth' => q{Doit fournir une option warning, une option critical ou les deux},
-       'range-noopt-size'   => q{Doit fournir une taille warning et/ou critical},
-       'range-nosize'       => q{Doit fournir une taille warning et/ou critical},
-       'range-notime'       => q{Doit fournir une heure warning et/ou critical},
-       'range-seconds'      => q{Argument invalide pour l'option « $1 » : doit être un nombre de secondes},
-       'range-version'      => q{doit être dans le format X.Y ou X.Y.Z, où X est le numéro de version majeure, },
-       'range-warnbig'      => q{L'option warning ne peut pas être plus grand que l'option critical},
-       'range-warnbigsize'  => q{L'option warning ($1 octets) ne peut pas être plus grand que l'option critical ($2 octets)},
-       'range-warnbigtime'  => q{L'option warning ($1 s) ne peut pas être plus grand que l'option critical ($2 s)},
-       'range-warnsmall'    => q{L'option warningne peut pas être plus petit que l'option critical},
-       'relsize-msg-ind'    => q{le plus gros index est « $1 » : $2},
-       'relsize-msg-reli'   => q{la plus grosse relation est l'index « $1 » : $2},
-       'relsize-msg-relt'   => q{la plus grosse relation est la table « $1 » : $2},
-       'relsize-msg-tab'    => q{la plus grosse table est « $1 » : $2},
-       'rep-badarg'         => q{Argument repinfo invalide : 6 valeurs séparées par des virgules attendues},
-       'rep-duh'            => q{Aucun sens à tester la réplication avec les mêmes valeurs},
-       'rep-fail'           => q{Ligne non répliquée sur l'esclave $1},
-       'rep-noarg'          => q{A besoin d'un argument repinfo},
-       'rep-norow'          => q{Ligne source de la réplication introuvable : $1},
-       'rep-noslaves'       => q{Aucun esclave trouvé},
-       'rep-notsame'        => q{Ne peut pas tester la réplication : les valeurs ne sont pas identiques},
-       'rep-ok'             => q{La ligne a été répliquée},
-       'rep-sourcefail'     => q{Échec de la mise à jour de la source},
-       'rep-timeout'        => q{La ligne n'a pas été répliquée. Délai dépassé : $1},
-       'rep-unknown'        => q{Échec du test de la réplication},
-       'rep-wrongvals'      => q{Ne peut pas tester la réplication : les valeurs ne sont pas les bonnes (ni $1 ni $2 ni $3)},
-       'runcommand-err'     => q{Erreur inconnue de la fonction « run_command »},
-       'runcommand-nodb'    => q{Aucune base de données cible trouvée},
-       'runcommand-nodupe'  => q{N'a pas pu dupliqué STDERR},
-       'runcommand-noerr'   => q{N'a pas pu ouvrir STDERR},
-       'runcommand-nosys'   => q{Échec de l'appel système avec un $1},
-       'runcommand-pgpass'  => q{Création du fichier pgpass temporaire $1},
-       'runcommand-timeout' => q{Délai épuisée pour la commande ! Essayez d'augmenter --timeout à une valeur plus importante que $1},
-       'runtime-badmrtg'    => q{queryname invalide ?},
-       'runtime-badname'    => q{Option invalide pour queryname option : doit être le nom d'une vue},
-       'runtime-msg'        => q{durée d'exécution de la requête : $1 secondes},
-       'same-failed'        => q{Les bases de données sont différentes. Éléments différents : $1},
-       'same-matched'       => q{Les bases de données ont les mêmes éléments},
-       'slony-noschema'     => q{N'a pas pu déterminer le schéma de Slony},
-       'slony-nonumber'     => q{L'appel à sl_status n'a pas renvoyé un numéro},
-       'slony-noparse'      => q{N'a pas pu analyser l'appel à sl_status},
-       'slony-lagtime'      => q{Durée de lag de Slony : $1},
-       'seq-die'            => q{N'a pas pu récupérer d'informations sur la séquence $1},
-       'seq-msg'            => q{$1=$2% (appels restant=$3)},
-       'seq-none'           => q{Aucune sequences trouvée},
-       'symlink-create'     => q{Création de « $1 »},
-       'symlink-done'       => q{Création impossible de « $1 »: $2 est déjà lié à "$3"},
-       'symlink-exists'     => q{Création impossible de « $1 »: le fichier $2 existe déjà},
-       'symlink-fail1'      => q{Échec de la suppression de « $1 » : $2},
-       'symlink-fail2'      => q{N'a pas pu supprimer le lien symbolique $1 vers $2 : $3},
-       'symlink-name'       => q{Cette commande ne fonctionnera pas sauf si le programme contient le mot « postgres »},
-       'symlink-unlink'     => q{Supression de « $1 » :$2 },
-       'testmode-end'       => q{FIN DU MODE DE TEST},
-       'testmode-fail'      => q{Échec de la connexion : $1 $2},
-       'testmode-norun'     => q{N'a pas pu exécuter « $1 » sur $2 : la version doit être supérieure ou égale à $3, mais est $4},
-       'testmode-noset'     => q{N'a pas pu exécuter « $1 » sur $2 : $3 n'est pas activé},
-       'testmode-nover'     => q{N'a pas pu trouver la version de $1},
-       'testmode-ok'        => q{Connexion OK : $1},
-       'testmode-start'     => q{DÉBUT DU MODE DE TEST},
-       'time-day'           => q{jour},
-       'time-days'          => q{jours},
-       'time-hour'          => q{heure},
-       'time-hours'         => q{heures},
-       'time-minute'        => q{minute},
-       'time-minutes'       => q{minutes},
-       'time-month'         => q{mois},
-       'time-months'        => q{mois},
-       'time-second'        => q{seconde},
-       'time-seconds'       => q{secondes},
-       'time-week'          => q{semaine},
-       'time-weeks'         => q{semaines},
-       'time-year'          => q{année},
-       'time-years'         => q{années},
-       'timesync-diff'      => q{ diff=$1}, ## needs leading space
-       'timesync-msg'       => q{timediff=$1 Base de données=$2 Local=$3},
-       'trigger-msg'        => q{Triggers désactivés : $1},
-       'txnidle-msg'        => q{transaction en attente la plus longue : $1s},
-       'txnidle-none'       => q{Aucun processus en attente dans une transaction},
-       'txntime-fail'       => q{Échec de la requête},
-       'txntime-msg'        => q{Transaction la plus longue : $1s},
-       'txntime-none'       => q{Aucune transaction},
-       'txnwrap-cbig'       => q{La valeur critique doit être inférieure à 2 milliards},
-       'txnwrap-wbig'       => q{La valeur d'avertissement doit être inférieure à 2 milliards},
-       'unknown-error'      => q{erreur inconnue},
-       'usage'              => qq{\nUsage: \$1 <options>\n Essayez « \$1 --help » pour liste complète des options\n\n},
-       'username'           => q{nom utilisateur},
-       'vac-msg'            => q{Base de données : $1 Table : $2},
-       'vac-nomatch-a'      => q{Aucune des tables correspondantes n'a eu d'opération ANALYZE},
-       'vac-nomatch-v'      => q{Aucune des tables correspondantes n'a eu d'opération VACUUM},
-       'version'            => q{version $1},
-       'version-badmrtg'    => q{Argument invalide pour la version de mrtg},
-       'version-fail'       => q{version $1, alors que la version attendue est $2},
-       'version-ok'         => q{version $1},
+    'address'            => q{adresse},
+    'backends-fatal'     => q{N'a pas pu se connecter : trop de connexions},
+    'backends-mrtg'      => q{DB=$1 Connexions maximum=$2},
+    'backends-msg'       => q{$1 connexions sur $2 ($3%)},
+    'backends-nomax'     => q{N'a pas pu déterminer max_connections},
+    'backends-oknone'    => q{Aucune connexion},
+    'backends-po'        => q{désolé, trop de clients sont déjà connectés},
+    'backends-users'     => q{$1 pour le nombre d'utilisateurs doit être un nombre ou un pourcentage},
+    'bloat-index'        => q{(db $1) index $2 lignes:$3 pages:$4 devrait être:$5 ($6X) octets perdus:$7 ($8)},
+    'bloat-nomin'        => q{aucune relation n'atteint le critère minimum de fragmentation},
+    'bloat-table'        => q{(db $1) table $2.$3 lignes:$4 pages:$5 devrait être:$6 ($7X) place perdue:$8 ($9)},
+    'checkpoint-baddir'  => q{data_directory invalide : "$1"},
+    'checkpoint-baddir2' => q{pg_controldata n'a pas pu lire le répertoire des données indiqué : « $1 »},
+    'checkpoint-badver'  => q{Échec lors de l'exécution de pg_controldata - probablement la mauvaise version},
+    'checkpoint-badver2' => q{Échec lors de l'exécution de pg_controldata - est-ce la bonne version ?},
+    'checkpoint-nodir'   => q{Vous devez fournir un argument --datadir ou configurer la variable d'environnement PGDATA},
+    'checkpoint-nodp'    => q{Vous devez installer le module Perl Date::Parse pour utiliser l'action checkpoint},
+    'checkpoint-noparse' => q{Incapable d'analyser le résultat de la commande pg_controldata : "$1"},
+    'checkpoint-noregex' => q{Échec de l'appel à pg_controldata $1},
+    'checkpoint-nosys'   => q{N'a pas pu appeler pg_controldata : $1},
+    'checkpoint-ok'      => q{Le dernier CHECKPOINT est survenu il y a une seconde},
+    'checkpoint-ok2'     => q{Le dernier CHECKPOINT est survenu il y a $1 secondes},
+    'checkpoint-po'      => q{Heure du dernier point de contr�le :},
+    'checksum-badline'   => q{Ligne pg_setting invalide : $1},
+    'checksum-msg'       => q{somme de contrôle : $1},
+    'checksum-nomd'      => q{Vous devez installer le module Perl Digest::MD5 pour utiliser l'action checksum},
+    'checksum-nomrtg'    => q{Vous devez fournir une somme de contrôle avec l'option --mrtg},
+    'custom-invalid'     => q{Format invalide renvoyé par la requête personnalisée},
+    'custom-norows'      => q{Aucune ligne renvoyée},
+    'custom-nostring'    => q{Vous devez fournir une requête},
+    'database'           => q{base de données},
+    'dbsize-version'     => q{La base de données cible doit être une version 8.1 ou ultérieure pour exécuter l'action database_size},
+    'die-action-version' => q{Ne peut pas exécuter « $1 » : la version du serveur doit être supérieure ou égale à $2, alors qu'elle est $3},
+    'die-badtime'        => q{La valeur de « $1 » doit être une heure valide. Par exemple, -$2 1s  -$2 « 10 minutes »},
+    'die-badversion'     => q{Version invalide : $1},
+    'die-noset'          => q{Ne peut pas exécuter « $1 » $2 n'est pas activé},
+    'die-nosetting'      => q{N'a pas pu récupérer le paramètre « $1 »},
+    'diskspace-fail'     => q{Résultat invalide pour la commande « $1 » : $2},
+    'diskspace-msg'      => q{Le système de fichiers $1 monté sur $2 utilise $3 sur $4 ($5%)},
+    'diskspace-nodata'   => q{N'a pas pu déterminer data_directory : êtes-vous connecté en tant que super-utilisateur ?},
+    'diskspace-nodf'     => q{N'a pas pu trouver l'exécutable /bin/df},
+    'diskspace-nodir'    => q{N'a pas pu trouver le répertoire des données « $1 »},
+    'file-noclose'       => q{N'a pas pu fermer $1 : $2},
+    'fsm-page-highver'   => q{Ne peut pas vérifier fsm_pages sur des serveurs en version 8.4 ou ultérieure},
+    'fsm-page-msg'       => q{emplacements de pages utilisés par la FSM : $1 sur $2 ($3%)},
+    'fsm-rel-highver'    => q{Ne peut pas vérifier fsm_relations sur des serveurs en version 8.4 ou ultérieure},
+    'fsm-rel-msg'        => q{relations tracées par la FSM : $1 sur $2 ($3%)},
+    'invalid-option'     => q{Option invalide},
+    'invalid-query'      => q{Une requête invalide a renvoyé : $1},
+    'listener-count'     => q{ en écoute=$1}, ## needs leading space
+    'listener-msg'       => q{processus LISTEN trouvés : $1},
+    'locks-msg'          => q{total des verrous « $1 » : $2},
+    'locks-msg2'         => q{total des verrous : $1},
+    'logfile-bad'        => q{Option logfile invalide « $1 »},
+    'logfile-debug'      => q{la destination est $1, le répertoire est $2, le fichier est $3, l'option facility est $4},
+    'logfile-debug2'     => q{Journal applicatif final : $1},
+    'logfile-dne'        => q{le journal applicatif $1 n'existe pas !},
+    'logfile-fail'       => q{échec pour tracer dans : $1},
+    'logfile-ok'         => q{trace dans : $1},
+    'logfile-openfail'   => q{échec pour l'ouverture du journal applicatif « $1 » : $2},
+    'logfile-opt-bad'    => q{Option logfile invalide},
+    'logfile-seekfail'   => q{Échec de la recherche dans $1 : $2},
+    'logfile-stderr'     => q{La sortie des traces a été redirigés stderr : merci de fournir un nom de fichier},
+    'logfile-syslog'     => q{La base de données utiliser syslog, merci de spécifier le chemin avec l'option --logfile (fac=$1)},
+    'maxtime'            => q{ maxtime=$1}, ## needs leading space
+    'mrtg-fail'          => q{Échec de l'action $1 : $2},
+    'new-bc-badver'      => q{N'a pas pu déterminer la version de Bucardo},
+    'new-bc-fail'        => q{N'a pas pu trouver la version actuelle pour Bucardo},
+    'new-bc-ok'          => q{La version $1 est la dernière pour Bucardo},
+    'new-bc-warn'        => q{Merci de mettre à jour vers la version $1 de Bucardo. Vous utilisez actuellement la $2},
+    'new-cp-fail'        => q{Incapable de déterminer la version actuelle de check_postgres.pl},
+    'new-cp-ok'          => q{La version $1 est la dernière pour check_postgres.pl},
+    'new-cp-warn'        => q{La version $1 de check_postgres.pl existe (ceci est la version $2)},
+    'new-pg-badver'      => q{N'a pas pu déterminer la révision de Postgres (la version était $1)},
+    'new-pg-badver2'     => q{N'a pas pu trouver l'information de révision de Posrgres version $1},
+    'new-pg-big'         => q{Veuillez mettre à jour Postgres vers la version $1. Vous utilisez actuellement la version $2},
+    'new-pg-match'       => q{Postgres est à la dernière révision ($1)},
+    'new-pg-small'       => q{La dernière version de Postgres est la $1, mais vous utilisez actuellement la version $2?},
+    'no-match-db'        => q{Aucune base de données trouvée à cause des options d'exclusion/inclusion},
+    'no-match-fs'        => q{Aucun système de fichier trouvé à cause des options d'exclusion/inclusion},
+    'no-match-rel'       => q{Aucune relation trouvée à cause des options d'exclusion/inclusion},
+    'no-match-set'       => q{Aucun paramètre trouvé à cause des options d'exclusion/inclusion},
+    'no-match-table'     => q{Aucune table trouvée à cause des options d'exclusion/inclusion},
+    'no-match-user'      => q{Aucune entrée trouvée à cause options d'exclusion/inclusion},
+    'no-time-hires'      => q{N'a pas trouvé le module Time::HiRes, nécessaire quand « showtime » est activé},
+    'opt-output-invalid' => q{Sortie invalide : doit être 'nagios' ou 'mrtg' ou 'simple' ou 'cacti'},
+    'opt-psql-badpath'   => q{Argument invalide pour psql : doit être le chemin complet vers un fichier nommé psql},
+    'opt-psql-noexec'    => q{ Le fichier « $1 » ne paraît pas exécutable},
+    'opt-psql-noexist'   => q{Ne peut pas trouver l'exécutable psql indiqué : $1},
+    'opt-psql-nofind'    => q{N'a pas pu trouver un psql exécutable},
+    'opt-psql-nover'     => q{N'a pas pu déterminer la version de psql},
+    'opt-psql-restrict'  => q{Ne peut pas utiliser l'option --PSQL si NO_PSQL_OPTION est activé},
+    'PID'                => q{PID},
+    'port'               => q{port},
+    'preptxn-none'       => q{Aucune transaction préparée trouvée},
+    'qtime-fail'         => q{Ne peut pas exécuter l'action txn_idle si stats_command_string est désactivé !},
+    'qtime-msg'          => q{requête la plus longue : $1s},
+    'qtime-nomatch'      => q{Aucune entrée correspondante n'a été trouvée},
+    'range-badcs'        => q{Option « $1 » invalide : doit être une somme de contrôle},
+    'range-badlock'      => q{Option « $1 » invalide : doit être un nombre de verrou ou « type1=#;type2=# »},
+    'range-badpercent'   => q{Option « $1 » invalide : doit être un pourcentage},
+    'range-badpercsize'  => q{Option « $1 » invalide : doit être une taille ou un pourcentage},
+    'range-badsize'      => q{Taille invalide pour l'option « $1 »},
+    'range-badtype'      => q{validate_range appelé avec un type inconnu « $1 »},
+    'range-badversion'   => q{Chaîne invalide pour l'option « $1 » : $2},
+    'range-cactionly'    => q{Cette action est pour cacti seulement et ne prend pas les arguments warning et critical},
+    'range-int'          => q{Argument invalide pour l'option « $1 » : doit être un entier},
+    'range-int-pos'      => q{Argument invalide pour l'option « $1 » : doit être un entier positif},
+    'range-neg-percent'  => q{Ne peut pas indiquer un pourcentage négatif !},
+    'range-none'         => q{Les options warning et critical ne sont pas nécessaires},
+    'range-noopt-both'   => q{Doit fournir les options warning et critical},
+    'range-noopt-one'    => q{Doit fournir une option warning ou critical},
+    'range-noopt-only'   => q{Peut seulement fournir une option warning ou critical},
+    'range-noopt-orboth' => q{Doit fournir une option warning, une option critical ou les deux},
+    'range-noopt-size'   => q{Doit fournir une taille warning et/ou critical},
+    'range-nosize'       => q{Doit fournir une taille warning et/ou critical},
+    'range-notime'       => q{Doit fournir une heure warning et/ou critical},
+    'range-seconds'      => q{Argument invalide pour l'option « $1 » : doit être un nombre de secondes},
+    'range-version'      => q{doit être dans le format X.Y ou X.Y.Z, où X est le numéro de version majeure, },
+    'range-warnbig'      => q{L'option warning ne peut pas être plus grand que l'option critical},
+    'range-warnbigsize'  => q{L'option warning ($1 octets) ne peut pas être plus grand que l'option critical ($2 octets)},
+    'range-warnbigtime'  => q{L'option warning ($1 s) ne peut pas être plus grand que l'option critical ($2 s)},
+    'range-warnsmall'    => q{L'option warningne peut pas être plus petit que l'option critical},
+    'relsize-msg-ind'    => q{le plus gros index est « $1 » : $2},
+    'relsize-msg-reli'   => q{la plus grosse relation est l'index « $1 » : $2},
+    'relsize-msg-relt'   => q{la plus grosse relation est la table « $1 » : $2},
+    'relsize-msg-tab'    => q{la plus grosse table est « $1 » : $2},
+    'rep-badarg'         => q{Argument repinfo invalide : 6 valeurs séparées par des virgules attendues},
+    'rep-duh'            => q{Aucun sens à tester la réplication avec les mêmes valeurs},
+    'rep-fail'           => q{Ligne non répliquée sur l'esclave $1},
+    'rep-noarg'          => q{A besoin d'un argument repinfo},
+    'rep-norow'          => q{Ligne source de la réplication introuvable : $1},
+    'rep-noslaves'       => q{Aucun esclave trouvé},
+    'rep-notsame'        => q{Ne peut pas tester la réplication : les valeurs ne sont pas identiques},
+    'rep-ok'             => q{La ligne a été répliquée},
+    'rep-sourcefail'     => q{Échec de la mise à jour de la source},
+    'rep-timeout'        => q{La ligne n'a pas été répliquée. Délai dépassé : $1},
+    'rep-unknown'        => q{Échec du test de la réplication},
+    'rep-wrongvals'      => q{Ne peut pas tester la réplication : les valeurs ne sont pas les bonnes (ni $1 ni $2 ni $3)},
+    'runcommand-err'     => q{Erreur inconnue de la fonction « run_command »},
+    'runcommand-nodb'    => q{Aucune base de données cible trouvée},
+    'runcommand-nodupe'  => q{N'a pas pu dupliqué STDERR},
+    'runcommand-noerr'   => q{N'a pas pu ouvrir STDERR},
+    'runcommand-nosys'   => q{Échec de l'appel système avec un $1},
+    'runcommand-pgpass'  => q{Création du fichier pgpass temporaire $1},
+    'runcommand-timeout' => q{Délai épuisée pour la commande ! Essayez d'augmenter --timeout à une valeur plus importante que $1},
+    'runtime-badmrtg'    => q{queryname invalide ?},
+    'runtime-badname'    => q{Option invalide pour queryname option : doit être le nom d'une vue},
+    'runtime-msg'        => q{durée d'exécution de la requête : $1 secondes},
+    'same-failed'        => q{Les bases de données sont différentes. Éléments différents : $1},
+    'same-matched'       => q{Les bases de données ont les mêmes éléments},
+    'slony-noschema'     => q{N'a pas pu déterminer le schéma de Slony},
+    'slony-nonumber'     => q{L'appel à sl_status n'a pas renvoyé un numéro},
+    'slony-noparse'      => q{N'a pas pu analyser l'appel à sl_status},
+    'slony-lagtime'      => q{Durée de lag de Slony : $1},
+    'seq-die'            => q{N'a pas pu récupérer d'informations sur la séquence $1},
+    'seq-msg'            => q{$1=$2% (appels restant=$3)},
+    'seq-none'           => q{Aucune sequences trouvée},
+    'symlink-create'     => q{Création de « $1 »},
+    'symlink-done'       => q{Création impossible de « $1 »: $2 est déjà lié à "$3"},
+    'symlink-exists'     => q{Création impossible de « $1 »: le fichier $2 existe déjà},
+    'symlink-fail1'      => q{Échec de la suppression de « $1 » : $2},
+    'symlink-fail2'      => q{N'a pas pu supprimer le lien symbolique $1 vers $2 : $3},
+    'symlink-name'       => q{Cette commande ne fonctionnera pas sauf si le programme contient le mot « postgres »},
+    'symlink-unlink'     => q{Supression de « $1 » :$2 },
+    'testmode-end'       => q{FIN DU MODE DE TEST},
+    'testmode-fail'      => q{Échec de la connexion : $1 $2},
+    'testmode-norun'     => q{N'a pas pu exécuter « $1 » sur $2 : la version doit être supérieure ou égale à $3, mais est $4},
+    'testmode-noset'     => q{N'a pas pu exécuter « $1 » sur $2 : $3 n'est pas activé},
+    'testmode-nover'     => q{N'a pas pu trouver la version de $1},
+    'testmode-ok'        => q{Connexion OK : $1},
+    'testmode-start'     => q{DÉBUT DU MODE DE TEST},
+    'time-day'           => q{jour},
+    'time-days'          => q{jours},
+    'time-hour'          => q{heure},
+    'time-hours'         => q{heures},
+    'time-minute'        => q{minute},
+    'time-minutes'       => q{minutes},
+    'time-month'         => q{mois},
+    'time-months'        => q{mois},
+    'time-second'        => q{seconde},
+    'time-seconds'       => q{secondes},
+    'time-week'          => q{semaine},
+    'time-weeks'         => q{semaines},
+    'time-year'          => q{année},
+    'time-years'         => q{années},
+    'timesync-diff'      => q{ diff=$1}, ## needs leading space
+    'timesync-msg'       => q{timediff=$1 Base de données=$2 Local=$3},
+    'trigger-msg'        => q{Triggers désactivés : $1},
+    'txnidle-msg'        => q{transaction en attente la plus longue : $1s},
+    'txnidle-none'       => q{Aucun processus en attente dans une transaction},
+    'txntime-fail'       => q{Échec de la requête},
+    'txntime-msg'        => q{Transaction la plus longue : $1s},
+    'txntime-none'       => q{Aucune transaction},
+    'txnwrap-cbig'       => q{La valeur critique doit être inférieure à 2 milliards},
+    'txnwrap-wbig'       => q{La valeur d'avertissement doit être inférieure à 2 milliards},
+    'unknown-error'      => q{erreur inconnue},
+    'usage'              => qq{\nUsage: \$1 <options>\n Essayez « \$1 --help » pour liste complète des options\n\n},
+    'username'           => q{nom utilisateur},
+    'vac-msg'            => q{Base de données : $1 Table : $2},
+    'vac-nomatch-a'      => q{Aucune des tables correspondantes n'a eu d'opération ANALYZE},
+    'vac-nomatch-v'      => q{Aucune des tables correspondantes n'a eu d'opération VACUUM},
+    'version'            => q{version $1},
+    'version-badmrtg'    => q{Argument invalide pour la version de mrtg},
+    'version-fail'       => q{version $1, alors que la version attendue est $2},
+    'version-ok'         => q{version $1},
 },
 'af' => {
 },
 'cs' => {
-       'checkpoint-po' => q{�as posledn�ho kontroln�ho bodu:},
+    'checkpoint-po' => q{�as posledn�ho kontroln�ho bodu:},
 },
 'de' => {
-       'backends-po'   => q{tut mir leid, schon zu viele Verbindungen},
-       'checkpoint-po' => q{Zeit des letzten Checkpoints:},
+    'backends-po'   => q{tut mir leid, schon zu viele Verbindungen},
+    'checkpoint-po' => q{Zeit des letzten Checkpoints:},
 },
 'es' => {
-       'backends-po'   => q{lo siento, ya tenemos demasiados clientes},
-       'checkpoint-po' => q{Instante de �ltimo checkpoint:},
+    'backends-po'   => q{lo siento, ya tenemos demasiados clientes},
+    'checkpoint-po' => q{Instante de �ltimo checkpoint:},
 },
 'fa' => {
-       'checkpoint-po' => q{زمان آخرین وارسی:},
+    'checkpoint-po' => q{زمان آخرین وارسی:},
 },
 'hr' => {
-       'backends-po' => q{nažalost, već je otvoreno previše klijentskih veza},
+    'backends-po' => q{nažalost, već je otvoreno previše klijentskih veza},
 },
 'hu' => {
-       'checkpoint-po' => q{A legut�bbi ellen�rz�pont ideje:},
+    'checkpoint-po' => q{A legut�bbi ellen�rz�pont ideje:},
 },
 'it' => {
-       'checkpoint-po' => q{Orario ultimo checkpoint:},
+    'checkpoint-po' => q{Orario ultimo checkpoint:},
 },
 'ja' => {
-       'backends-po'   => q{現在クライアント数が多すぎます},
-       'checkpoint-po' => q{最終チェックポイント時刻:},
+    'backends-po'   => q{現在クライアント数が多すぎます},
+    'checkpoint-po' => q{最終チェックポイント時刻:},
 },
 'ko' => {
-       'backends-po'   => q{최대 동시 접속자 수를 초과했습니다.},
-       'checkpoint-po' => q{������ üũ����Ʈ �ð�:},
+    'backends-po'   => q{최대 동시 접속자 수를 초과했습니다.},
+    'checkpoint-po' => q{������ üũ����Ʈ �ð�:},
 },
 'nb' => {
-       'backends-po'   => q{beklager, for mange klienter},
-       'checkpoint-po' => q{Tidspunkt for nyeste kontrollpunkt:},
+    'backends-po'   => q{beklager, for mange klienter},
+    'checkpoint-po' => q{Tidspunkt for nyeste kontrollpunkt:},
 },
 'nl' => {
 },
 'pl' => {
-       'checkpoint-po' => q{Czas najnowszego punktu kontrolnego:},
+    'checkpoint-po' => q{Czas najnowszego punktu kontrolnego:},
 },
 'pt_BR' => {
-       'backends-po'   => q{desculpe, muitos clientes conectados},
-       'checkpoint-po' => q{Hora do último ponto de controle:},
+    'backends-po'   => q{desculpe, muitos clientes conectados},
+    'checkpoint-po' => q{Hora do último ponto de controle:},
 },
 'ro' => {
-       'checkpoint-po' => q{Timpul ultimului punct de control:},
+    'checkpoint-po' => q{Timpul ultimului punct de control:},
 },
 'ru' => {
-       'backends-po'   => q{��������, ��� ������� ����� ��������},
-       'checkpoint-po' => q{����� ��������� checkpoint:},
+    'backends-po'   => q{��������, ��� ������� ����� ��������},
+    'checkpoint-po' => q{����� ��������� checkpoint:},
 },
 'sk' => {
-       'backends-po'   => q{je mi ��to, je u� pr�li� ve�a klientov},
-       'checkpoint-po' => q{Čas posledného kontrolného bodu:},
+    'backends-po'   => q{je mi ��to, je u� pr�li� ve�a klientov},
+    'checkpoint-po' => q{Čas posledného kontrolného bodu:},
 },
 'sl' => {
-       'backends-po'   => q{povezanih je �e preve� odjemalcev},
-       'checkpoint-po' => q{�as zadnje kontrolne to�ke ............},
+    'backends-po'   => q{povezanih je �e preve� odjemalcev},
+    'checkpoint-po' => q{�as zadnje kontrolne to�ke ............},
 },
 'sv' => {
-       'backends-po'   => q{ledsen, f�r m�nga klienter},
-       'checkpoint-po' => q{Tidpunkt f�r senaste kontrollpunkt:},
+    'backends-po'   => q{ledsen, f�r m�nga klienter},
+    'checkpoint-po' => q{Tidpunkt f�r senaste kontrollpunkt:},
 },
 'ta' => {
-       'checkpoint-po' => q{நவீன சோதனை மையத்தின் நேரம்:},
+    'checkpoint-po' => q{நவீன சோதனை மையத்தின் நேரம்:},
 },
 'tr' => {
-       'backends-po'   => q{üzgünüm, istemci sayısı çok fazla},
-       'checkpoint-po' => q{En son checkpoint'in zamanı:},
+    'backends-po'   => q{üzgünüm, istemci sayısı çok fazla},
+    'checkpoint-po' => q{En son checkpoint'in zamanı:},
 },
 'zh_CN' => {
-       'backends-po'   => q{�Բ���, �Ѿ���̫���Ŀͻ�},
-       'checkpoint-po' => q{���¼�������ʱ��:},
+    'backends-po'   => q{�Բ���, �Ѿ���̫���Ŀͻ�},
+    'checkpoint-po' => q{���¼�������ʱ��:},
 },
 'zh_TW' => {
-       'backends-po'   => q{對不起,用戶端過多},
-       'checkpoint-po' => q{最新的檢查點時間:},
+    'backends-po'   => q{對不起,用戶端過多},
+    'checkpoint-po' => q{最新的檢查點時間:},
 },
 );
 ## use critic
@@ -612,139 +612,139 @@ $opt{timeout} = 30;
 
 ## This option must come before the GetOptions call
 for my $arg (@ARGV) {
-       if ($arg eq '--no-check_postgresrc') {
-               $opt{'no-check_postgresrc'} = 1;
-               last;
-       }
+    if ($arg eq '--no-check_postgresrc') {
+        $opt{'no-check_postgresrc'} = 1;
+        last;
+    }
 }
 
 my $rcfile;
 if (! $opt{'no-check_postgresrc'}) {
-       if (-e '.check_postgresrc') {
-               $rcfile = '.check_postgresrc';
-       }
-       elsif (-e "$ENV{HOME}/.check_postgresrc") {
-               $rcfile = "$ENV{HOME}/.check_postgresrc";
-       }
-       elsif (-e '/etc/check_postgresrc') {
-               $rcfile = '/etc/check_postgresrc';
-       }
+    if (-e '.check_postgresrc') {
+        $rcfile = '.check_postgresrc';
+    }
+    elsif (-e "$ENV{HOME}/.check_postgresrc") {
+        $rcfile = "$ENV{HOME}/.check_postgresrc";
+    }
+    elsif (-e '/etc/check_postgresrc') {
+        $rcfile = '/etc/check_postgresrc';
+    }
 }
 ## We need a temporary hash so that multi-value options can be overridden on the command line
 my %tempopt;
 if (defined $rcfile) {
-       open my $rc, '<', $rcfile or die qq{Could not open "$rcfile": $!\n};
-       RCLINE:
-       while (<$rc>) {
-               next if /^\s*#/;
-               next unless /^\s*(\w+)\s*=\s*(.+?)\s*$/o;
-               my ($name,$value) = ($1,$2); ## no critic (ProhibitCaptureWithoutTest)
-               ## Map alternate option spellings to preferred names
-               if ($name eq 'dbport' or $name eq 'p' or $name eq 'dbport1' or $name eq 'p1' or $name eq 'port1') {
-                       $name = 'port';
-               }
-               elsif ($name eq 'dbhost' or $name eq 'H' or $name eq 'dbhost1' or $name eq 'H1' or $name eq 'host1') {
-                       $name = 'host';
-               }
-               elsif ($name eq 'db' or $name eq 'db1' or $name eq 'dbname1') {
-                       $name = 'dbname';
-               }
-               elsif ($name eq 'u' or $name eq 'u1' or $name eq 'dbuser1') {
-                       $name = 'dbuser';
-               }
-               if ($name eq 'dbport2' or $name eq 'p2') {
-                       $name = 'port2';
-               }
-               elsif ($name eq 'dbhost2' or $name eq 'H2') {
-                       $name = 'host2';
-               }
-               elsif ($name eq 'db2') {
-                       $name = 'dbname2';
-               }
-               elsif ($name eq 'u2') {
-                       $name = 'dbuser2';
-               }
-
-               ## These options are multiples ('@s')
-               for my $arr (qw/include exclude includeuser excludeuser host port dbuser dbname dbpass dbservice/) {
-                       next if $name ne $arr and $name ne "${arr}2";
-                       push @{$tempopt{$name}} => $value;
-                       ## Don't set below as a normal value
-                       next RCLINE;
-               }
-               $opt{$name} = $value;
-       }
-       close $rc or die;
+    open my $rc, '<', $rcfile or die qq{Could not open "$rcfile": $!\n};
+    RCLINE:
+    while (<$rc>) {
+        next if /^\s*#/;
+        next unless /^\s*(\w+)\s*=\s*(.+?)\s*$/o;
+        my ($name,$value) = ($1,$2); ## no critic (ProhibitCaptureWithoutTest)
+        ## Map alternate option spellings to preferred names
+        if ($name eq 'dbport' or $name eq 'p' or $name eq 'dbport1' or $name eq 'p1' or $name eq 'port1') {
+            $name = 'port';
+        }
+        elsif ($name eq 'dbhost' or $name eq 'H' or $name eq 'dbhost1' or $name eq 'H1' or $name eq 'host1') {
+            $name = 'host';
+        }
+        elsif ($name eq 'db' or $name eq 'db1' or $name eq 'dbname1') {
+            $name = 'dbname';
+        }
+        elsif ($name eq 'u' or $name eq 'u1' or $name eq 'dbuser1') {
+            $name = 'dbuser';
+        }
+        if ($name eq 'dbport2' or $name eq 'p2') {
+            $name = 'port2';
+        }
+        elsif ($name eq 'dbhost2' or $name eq 'H2') {
+            $name = 'host2';
+        }
+        elsif ($name eq 'db2') {
+            $name = 'dbname2';
+        }
+        elsif ($name eq 'u2') {
+            $name = 'dbuser2';
+        }
+
+        ## These options are multiples ('@s')
+        for my $arr (qw/include exclude includeuser excludeuser host port dbuser dbname dbpass dbservice/) {
+            next if $name ne $arr and $name ne "${arr}2";
+            push @{$tempopt{$name}} => $value;
+            ## Don't set below as a normal value
+            next RCLINE;
+        }
+        $opt{$name} = $value;
+    }
+    close $rc or die;
 }
 
 die $USAGE unless
-       GetOptions(
-                          \%opt,
-                          'version|V',
-                          'verbose|v+',
-                          'help|h',
-                          'man',
-                          'output=s',
-                          'simple',
-                          'showperf=i',
-                          'perflimit=i',
-                          'showtime=i',
-                          'timeout|t=i',
-                          'test',
-                          'symlinks',
-                          'debugoutput=s',
-                          'no-check_postgresrc',
-
-                          'action=s',
-                          'warning=s',
-                          'critical=s',
-                          'include=s@',
-                          'exclude=s@',
-                          'includeuser=s@',
-                          'excludeuser=s@',
-
-                          'host|dbhost|H|dbhost1|H1=s@',
-                          'port|dbport|p|port1|dbport1|p1=s@',
-                          'dbname|db|dbname1|db1=s@',
-                          'dbuser|u|dbuser1|u1=s@',
-                          'dbpass|dbpass1=s@',
-                          'dbservice|dbservice1=s@',
-
-                          'host2|dbhost2|H2=s@',
-                          'port2|dbport2|p2=s@',
-                          'dbname2|db2=s@',
-                          'dbuser2|u2=s@',
-                          'dbpass2=s@',
-                          'dbservice2=s@',
-
-                          'PSQL=s',
-
-                          'tempdir=s',
-                          'get_method=s',
-                          'language=s',
-                          'mrtg=s',      ## used by MRTG checks only
-                          'logfile=s',   ## used by check_logfile only
-                          'queryname=s', ## used by query_runtime only
-                          'query=s',     ## used by custom_query only
-                          'valtype=s',   ## used by custom_query only
-                          'reverse',     ## used by custom_query only
-                          'repinfo=s',   ## used by replicate_row only
-                          'noidle',      ## used by backends only
-                          'datadir=s',   ## used by checkpoint only
-                          'schema=s',    ## used by slony_status only
-                          )
-       and keys %opt
-       and ! @ARGV;
+    GetOptions(
+               \%opt,
+               'version|V',
+               'verbose|v+',
+               'help|h',
+               'man',
+               'output=s',
+               'simple',
+               'showperf=i',
+               'perflimit=i',
+               'showtime=i',
+               'timeout|t=i',
+               'test',
+               'symlinks',
+               'debugoutput=s',
+               'no-check_postgresrc',
+
+               'action=s',
+               'warning=s',
+               'critical=s',
+               'include=s@',
+               'exclude=s@',
+               'includeuser=s@',
+               'excludeuser=s@',
+
+               'host|dbhost|H|dbhost1|H1=s@',
+               'port|dbport|p|port1|dbport1|p1=s@',
+               'dbname|db|dbname1|db1=s@',
+               'dbuser|u|dbuser1|u1=s@',
+               'dbpass|dbpass1=s@',
+               'dbservice|dbservice1=s@',
+
+               'host2|dbhost2|H2=s@',
+               'port2|dbport2|p2=s@',
+               'dbname2|db2=s@',
+               'dbuser2|u2=s@',
+               'dbpass2=s@',
+               'dbservice2=s@',
+
+               'PSQL=s',
+
+               'tempdir=s',
+               'get_method=s',
+               'language=s',
+               'mrtg=s',      ## used by MRTG checks only
+               'logfile=s',   ## used by check_logfile only
+               'queryname=s', ## used by query_runtime only
+               'query=s',     ## used by custom_query only
+               'valtype=s',   ## used by custom_query only
+               'reverse',     ## used by custom_query only
+               'repinfo=s',   ## used by replicate_row only
+               'noidle',      ## used by backends only
+               'datadir=s',   ## used by checkpoint only
+               'schema=s',    ## used by slony_status only
+               )
+    and keys %opt
+    and ! @ARGV;
 
 if ( $opt{man} ) {
-       require Pod::Usage;
-       Pod::Usage::pod2usage({-verbose => 2});
-       exit;
+    require Pod::Usage;
+    Pod::Usage::pod2usage({-verbose => 2});
+    exit;
 }
 
 ## Put multi-val options from check_postgresrc in place, only if no command-line args!
 for my $mv (keys %tempopt) {
-       $opt{$mv} ||= delete $tempopt{$mv};
+    $opt{$mv} ||= delete $tempopt{$mv};
 }
 
 our $VERBOSE = $opt{verbose} || 0;
@@ -753,26 +753,26 @@ our $OUTPUT = lc $opt{output} || '';
 
 ## Allow the optimization of the get_methods list by an argument
 if ($opt{get_method}) {
-       my $found = 0;
-       for my $meth (@get_methods) {
-               if ($meth =~ /^$opt{get_method}/io) {
-                       @get_methods = ($meth);
-                       $found = 1;
-                       last;
-               }
-       }
-       if (!$found) {
-               print "Unknown value for get_method: $opt{get_method}\n";
-               print "Valid choices are:\n";
-               print (join "\n" => map { s/(\w+).*/$1/; $_ } @get_methods);
-               print "\n";
-               exit;
-       }
+    my $found = 0;
+    for my $meth (@get_methods) {
+        if ($meth =~ /^$opt{get_method}/io) {
+            @get_methods = ($meth);
+            $found = 1;
+            last;
+        }
+    }
+    if (!$found) {
+        print "Unknown value for get_method: $opt{get_method}\n";
+        print "Valid choices are:\n";
+        print (join "\n" => map { s/(\w+).*/$1/; $_ } @get_methods);
+        print "\n";
+        exit;
+    }
 }
 
 ## Allow the language to be changed by an explicit option
 if ($opt{language}) {
-       $lang = substr($opt{language},0,2);
+    $lang = substr($opt{language},0,2);
 }
 
 ## Output the actual string returned by psql in the normal output
@@ -785,30 +785,30 @@ our $DEBUG_INFO = '?';
 ## then fall back to the default.
 
 if (!$OUTPUT) {
-       my $dir = getcwd;
-       if ($dir =~ /(nagios|mrtg|simple|cacti)/io) {
-               $OUTPUT = lc $1;
-       }
-       elsif ($opt{simple}) {
-               $OUTPUT = 'simple';
-       }
-       else {
-               $OUTPUT = $DEFAULT_OUTPUT;
-       }
+    my $dir = getcwd;
+    if ($dir =~ /(nagios|mrtg|simple|cacti)/io) {
+        $OUTPUT = lc $1;
+    }
+    elsif ($opt{simple}) {
+        $OUTPUT = 'simple';
+    }
+    else {
+        $OUTPUT = $DEFAULT_OUTPUT;
+    }
 }
 
 
 ## Extract transforms from the output
 $opt{transform} = '';
 if ($OUTPUT =~ /\b(kb|mb|gb|tb|eb)\b/) {
-       $opt{transform} = uc $1;
+    $opt{transform} = uc $1;
 }
 if ($OUTPUT =~ /(nagios|mrtg|simple|cacti)/io) {
-       $OUTPUT = lc $1;
+    $OUTPUT = lc $1;
 }
 ## Check for a valid output setting
 if ($OUTPUT ne 'nagios' and $OUTPUT ne 'mrtg' and $OUTPUT ne 'simple' and $OUTPUT ne 'cacti') {
-       die msgn('opt-output-invalid');
+    die msgn('opt-output-invalid');
 }
 
 our $MRTG = ($OUTPUT eq 'mrtg' or $OUTPUT eq 'simple') ? 1 : 0;
@@ -818,14 +818,14 @@ our $SIMPLE = $OUTPUT eq 'simple' ? 1 : 0;
 ## See if we need to invoke something based on our name
 our $action = $opt{action} || '';
 if ($ME =~ /check_postgres_(\w+)/) {
-       $action = $1;
+    $action = $1;
 }
 
 $VERBOSE >= 3 and warn Dumper \%opt;
 
 if ($opt{version}) {
-       print qq{$ME2 version $VERSION\n};
-       exit 0;
+    print qq{$ME2 version $VERSION\n};
+    exit 0;
 }
 
 ## Quick hash to put normal action information in one place:
@@ -877,15 +877,15 @@ our $action_info = {
 our $action_usage = '';
 our $longname = 1;
 for (keys %$action_info) {
-       $longname = length($_) if length($_) > $longname;
+    $longname = length($_) if length($_) > $longname;
 }
 for (sort keys %$action_info) {
-       $action_usage .= sprintf " %-*s - %s\n", 2+$longname, $_, $action_info->{$_}[1];
+    $action_usage .= sprintf " %-*s - %s\n", 2+$longname, $_, $action_info->{$_}[1];
 }
 
 
 if ($opt{help}) {
-       print qq{Usage: $ME2 <options>
+    print qq{Usage: $ME2 <options>
 Run various tests against one or more Postgres databases.
 Returns with an exit code of 0 (success), 1 (warning), 2 (critical), or 3 (unknown)
 This is version $VERSION.
@@ -929,7 +929,7 @@ Or visit: http://bucardo.org/check_postgres/
 
 
 };
-       exit 0;
+    exit 0;
 }
 
 build_symlinks() if $opt{symlinks};
@@ -945,81 +945,81 @@ build_symlinks() if $action =~ /build_symlinks/; ## Does not return, may be 'bui
 
 ## Die if Time::HiRes is needed but not found
 if ($opt{showtime}) {
-       eval {
-               require Time::HiRes;
-               import Time::HiRes qw/gettimeofday tv_interval sleep/;
-       };
-       if ($@) {
-               die msg('no-time-hires');
-       }
+    eval {
+        require Time::HiRes;
+        import Time::HiRes qw/gettimeofday tv_interval sleep/;
+    };
+    if ($@) {
+        die msg('no-time-hires');
+    }
 }
 
 ## We don't (usually) want to die, but want a graceful Nagios-like exit instead
 sub ndie {
-       eval { File::Temp::cleanup(); };
-       my $msg = shift;
-       chomp $msg;
-       print "ERROR: $msg\n";
-       exit 3;
+    eval { File::Temp::cleanup(); };
+    my $msg = shift;
+    chomp $msg;
+    print "ERROR: $msg\n";
+    exit 3;
 }
 
 sub msg { ## no critic
 
-       my $name = shift || '?';
-
-       my $msg = '';
-
-       if (exists $msg{$lang}{$name}) {
-               $msg = $msg{$lang}{$name};
-       }
-       elsif (exists $msg{'en'}{$name}) {
-               $msg = $msg{'en'}{$name};
-       }
-       else {
-               my $line = (caller)[2];
-               die qq{Invalid message "$name" from line $line\n};
-       }
-
-       my $x=1;
-       {
-               my $val = $_[$x-1];
-               $val = '?' if ! defined $val;
-               last unless $msg =~ s/\$$x/$val/g;
-               $x++;
-               redo;
-       }
-       return $msg;
+    my $name = shift || '?';
+
+    my $msg = '';
+
+    if (exists $msg{$lang}{$name}) {
+        $msg = $msg{$lang}{$name};
+    }
+    elsif (exists $msg{'en'}{$name}) {
+        $msg = $msg{'en'}{$name};
+    }
+    else {
+        my $line = (caller)[2];
+        die qq{Invalid message "$name" from line $line\n};
+    }
+
+    my $x=1;
+    {
+        my $val = $_[$x-1];
+        $val = '?' if ! defined $val;
+        last unless $msg =~ s/\$$x/$val/g;
+        $x++;
+        redo;
+    }
+    return $msg;
 
 } ## end of msg
 
 sub msgn { ## no critic
-       return msg(@_) . "\n";
+    return msg(@_) . "\n";
 }
 
 sub msg_en {
 
-       my $name = shift || '?';
+    my $name = shift || '?';
 
-       return $msg{'en'}{$name};
+    return $msg{'en'}{$name};
 
 } ## end of msg_en
 
 ## Everything from here on out needs psql, so find and verify a working version:
 if ($NO_PSQL_OPTION) {
-       delete $opt{PSQL} and ndie msg('opt-psql-restrict');
+    delete $opt{PSQL} and ndie msg('opt-psql-restrict');
 }
 
 if (! defined $PSQL or ! length $PSQL) {
-       if (exists $opt{PSQL}) {
-               $PSQL = $opt{PSQL};
-               $PSQL =~ m{^/[\w\d\/]*psql$} or ndie msg('opt-psql-badpath');
-               -e $PSQL or ndie msg('opt-psql-noexist', $PSQL);
-       }
-       else {
-               my $psql = $ENV{PGBINDIR} ? "$ENV{PGBINDIR}/psql" : 'psql';
-               chomp($PSQL = qx{which $psql});
-               $PSQL or ndie msg('opt-psql-nofind');
-       }
+    if (exists $opt{PSQL}) {
+        $PSQL = $opt{PSQL};
+        $PSQL =~ m{^/[\w\d\/]*psql$} or ndie msg('opt-psql-badpath');
+        -e $PSQL or ndie msg('opt-psql-noexist', $PSQL);
+    }
+    else {
+        my $psql = $ENV{PGBINDIR} ? "$ENV{PGBINDIR}/psql" : 'psql';
+        chomp($PSQL = qx{which $psql});
+        $PSQL or ndie msg('opt-psql-nofind');
+    }
 }
 -x $PSQL or ndie msg('opt-psql-noexec', $PSQL);
 $res = qx{$PSQL --version};
@@ -1035,190 +1035,190 @@ $opt{defaultdb} = 'pgbouncer' if $action eq 'pgbouncer_checksum';
 
 sub add_response {
 
-       my ($type,$msg) = @_;
-
-       $db->{host} ||= '';
-
-       if (defined $opt{dbname2} and defined $opt{dbname2}->[0] and length $opt{dbname2}->[0]
-               and $opt{dbname}->[0] ne $opt{dbname2}->[0]) {
-               $db->{dbname} .= " => $opt{dbname2}->[0]";
-       }
-       if (defined $opt{host2} and defined $opt{host2}->[0] and length $opt{host2}->[0]
-               and $opt{host}->[0] ne $opt{host2}->[0]) {
-               $db->{host} .= " => $opt{host2}->[0]";
-       }
-       if (defined $opt{port2} and defined $opt{port2}->[0] and length $opt{port2}->[0]
-               and $opt{port}->[0] ne $opt{port2}->[0]) {
-               $db->{port} .= " => $opt{port2}->[0]) ";
-       }
-       if ($nohost) {
-               push @{$type->{''}} => [$msg, length $nohost > 1 ? $nohost : ''];
-               return;
-       }
-
-       my $dbservice = $db->{dbservice};
-       my $dbname    = $db->{dbname};
-       my $header = sprintf q{%s%s%s},
-               $action_info->{$action}[0] ? '' : (defined $dbservice and length $dbservice) ?
-                       qq{service=$dbservice } : qq{DB "$dbname" },
-                               $db->{host} eq '<none>' ? '' : qq{(host:$db->{host}) },
-                                       defined $db->{port} ? ($db->{port} eq $opt{defaultport} ? '' : qq{(port=$db->{port}) }) : '';
-       $header =~ s/\s+$//;
-       my $perf = ($opt{showtime} and $db->{totaltime}) ? "time=$db->{totaltime}" : '';
-       if ($db->{perf}) {
-               $perf .= " $db->{perf}";
-       }
-       push @{$type->{$header}} => [$msg,$perf];
-
-       return;
+    my ($type,$msg) = @_;
+
+    $db->{host} ||= '';
+
+    if (defined $opt{dbname2} and defined $opt{dbname2}->[0] and length $opt{dbname2}->[0]
+        and $opt{dbname}->[0] ne $opt{dbname2}->[0]) {
+        $db->{dbname} .= " => $opt{dbname2}->[0]";
+    }
+    if (defined $opt{host2} and defined $opt{host2}->[0] and length $opt{host2}->[0]
+        and $opt{host}->[0] ne $opt{host2}->[0]) {
+        $db->{host} .= " => $opt{host2}->[0]";
+    }
+    if (defined $opt{port2} and defined $opt{port2}->[0] and length $opt{port2}->[0]
+        and $opt{port}->[0] ne $opt{port2}->[0]) {
+        $db->{port} .= " => $opt{port2}->[0]) ";
+    }
+    if ($nohost) {
+        push @{$type->{''}} => [$msg, length $nohost > 1 ? $nohost : ''];
+        return;
+    }
+
+    my $dbservice = $db->{dbservice};
+    my $dbname    = $db->{dbname};
+    my $header = sprintf q{%s%s%s},
+        $action_info->{$action}[0] ? '' : (defined $dbservice and length $dbservice) ?
+            qq{service=$dbservice } : qq{DB "$dbname" },
+                $db->{host} eq '<none>' ? '' : qq{(host:$db->{host}) },
+                    defined $db->{port} ? ($db->{port} eq $opt{defaultport} ? '' : qq{(port=$db->{port}) }) : '';
+    $header =~ s/\s+$//;
+    my $perf = ($opt{showtime} and $db->{totaltime}) ? "time=$db->{totaltime}" : '';
+    if ($db->{perf}) {
+        $perf .= " $db->{perf}";
+    }
+    push @{$type->{$header}} => [$msg,$perf];
+
+    return;
 
 } ## end of add_response
 
 
 sub add_unknown {
-       my $msg = shift || $db->{error};
-       $msg =~ s/[\r\n]\s*/\\n /g;
-       $msg =~ s/\|/<PIPE>/g if $opt{showperf};
-       add_response \%unknown, $msg;
+    my $msg = shift || $db->{error};
+    $msg =~ s/[\r\n]\s*/\\n /g;
+    $msg =~ s/\|/<PIPE>/g if $opt{showperf};
+    add_response \%unknown, $msg;
 }
 sub add_critical {
-       add_response \%critical, shift;
+    add_response \%critical, shift;
 }
 sub add_warning {
-       add_response \%warning, shift;
+    add_response \%warning, shift;
 }
 sub add_ok {
-       add_response \%ok, shift;
+    add_response \%ok, shift;
 }
 
 
 sub do_mrtg {
-       ## Hashref of info to pass out for MRTG or stat
-       my $arg = shift;
-       my $one = $arg->{one} || 0;
-       my $two = $arg->{two} || 0;
-       if ($SIMPLE) {
-               $one = $two if (length $two and $two > $one);
-               if ($opt{transform} eq 'KB' and $one =~ /^\d+$/) {
-                       $one = int $one/(1024);
-               }
-               if ($opt{transform} eq 'MB' and $one =~ /^\d+$/) {
-                       $one = int $one/(1024*1024);
-               }
-               elsif ($opt{transform} eq 'GB' and $one =~ /^\d+$/) {
-                       $one = int $one/(1024*1024*1024);
-               }
-               elsif ($opt{transform} eq 'TB' and $one =~ /^\d+$/) {
-                       $one = int $one/(1024*1024*1024*1024);
-               }
-               elsif ($opt{transform} eq 'EB' and $one =~ /^\d+$/) {
-                       $one = int $one/(1024*1024*1024*1024*1024);
-               }
-               print "$one\n";
-       }
-       else {
-               my $uptime = $arg->{uptime} || '';
-               my $message = $arg->{msg} || '';
-               print "$one\n$two\n$uptime\n$message\n";
-       }
-       exit 0;
+    ## Hashref of info to pass out for MRTG or stat
+    my $arg = shift;
+    my $one = $arg->{one} || 0;
+    my $two = $arg->{two} || 0;
+    if ($SIMPLE) {
+        $one = $two if (length $two and $two > $one);
+        if ($opt{transform} eq 'KB' and $one =~ /^\d+$/) {
+            $one = int $one/(1024);
+        }
+        if ($opt{transform} eq 'MB' and $one =~ /^\d+$/) {
+            $one = int $one/(1024*1024);
+        }
+        elsif ($opt{transform} eq 'GB' and $one =~ /^\d+$/) {
+            $one = int $one/(1024*1024*1024);
+        }
+        elsif ($opt{transform} eq 'TB' and $one =~ /^\d+$/) {
+            $one = int $one/(1024*1024*1024*1024);
+        }
+        elsif ($opt{transform} eq 'EB' and $one =~ /^\d+$/) {
+            $one = int $one/(1024*1024*1024*1024*1024);
+        }
+        print "$one\n";
+    }
+    else {
+        my $uptime = $arg->{uptime} || '';
+        my $message = $arg->{msg} || '';
+        print "$one\n$two\n$uptime\n$message\n";
+    }
+    exit 0;
 }
 
 
 sub bad_mrtg {
-       my $msg = shift;
-       $ERROR and ndie $ERROR;
-       warn msgn('mrtg-fail', $action, $msg);
-       exit 3;
+    my $msg = shift;
+    $ERROR and ndie $ERROR;
+    warn msgn('mrtg-fail', $action, $msg);
+    exit 3;
 }
 
 
 sub do_mrtg_stats {
 
-       ## Show the two highest items for mrtg stats hash
-
-       my $msg = shift || msg('unknown-error');
-
-       keys %stats or bad_mrtg($msg);
-       my ($one,$two) = ('','');
-       for (sort { $stats{$b} <=> $stats{$a} } keys %stats) {
-               if ($one eq '') {
-                       $one = $stats{$_};
-                       $msg = exists $statsmsg{$_} ? $statsmsg{$_} : "DB: $_";
-                       next;
-               }
-               $two = $stats{$_};
-               last;
-       }
-       do_mrtg({one => $one, two => $two, msg => $msg});
+    ## Show the two highest items for mrtg stats hash
+
+    my $msg = shift || msg('unknown-error');
+
+    keys %stats or bad_mrtg($msg);
+    my ($one,$two) = ('','');
+    for (sort { $stats{$b} <=> $stats{$a} } keys %stats) {
+        if ($one eq '') {
+            $one = $stats{$_};
+            $msg = exists $statsmsg{$_} ? $statsmsg{$_} : "DB: $_";
+            next;
+        }
+        $two = $stats{$_};
+        last;
+    }
+    do_mrtg({one => $one, two => $two, msg => $msg});
 }
 
 
 sub finishup {
 
-       ## Final output
-       ## These are meant to be compact and terse: sometimes messages go to pagers
-
-       $MRTG and do_mrtg_stats();
-
-       $action =~ s/^\s*(\S+)\s*$/$1/;
-       my $service = sprintf "%s$action", $FANCYNAME ? 'postgres_' : '';
-       if (keys %critical or keys %warning or keys %ok or keys %unknown) {
-               printf '%s ', $YELLNAME ? uc $service : $service;
-       }
-
-       sub dumpresult {
-               my ($type,$info) = @_;
-               my $SEP = ' * ';
-               ## Are we showing DEBUG_INFO?
-               my $showdebug = 0;
-               if ($DEBUGOUTPUT) {
-                       $showdebug = 1 if $DEBUGOUTPUT =~ /a/io
-                               or ($DEBUGOUTPUT =~ /c/io and $type eq 'c')
-                               or ($DEBUGOUTPUT =~ /w/io and $type eq 'w')
-                               or ($DEBUGOUTPUT =~ /o/io and $type eq 'o')
-                               or ($DEBUGOUTPUT =~ /u/io and $type eq 'u');
-               }
-               for (sort keys %$info) {
-                       printf "$_ %s%s ",
-                               $showdebug ? "[DEBUG: $DEBUG_INFO] " : '',
-                               join $SEP => map { $_->[0] } @{$info->{$_}};
-               }
-               if ($opt{showperf}) {
-                       print '| ';
-                       for (sort keys %$info) {
-                               my $m = sprintf '%s ', join $SEP => map { $_->[1] } @{$info->{$_}};
-                               if ($VERBOSE) {
-                                       $m =~ s/  /\n/g;
-                               }
-                               print $m;
-                       }
-               }
-               print "\n";
-       }
-
-       if (keys %critical) {
-               print 'CRITICAL: ';
-               dumpresult(c => \%critical);
-               exit 2;
-       }
-       if (keys %warning) {
-               print 'WARNING: ';
-               dumpresult(w => \%warning);
-               exit 1;
-       }
-       if (keys %ok) {
-               print 'OK: ';
-               dumpresult(o => \%ok);
-               exit 0;
-       }
-       if (keys %unknown) {
-               print 'UNKNOWN: ';
-               dumpresult(u => \%unknown);
-               exit 3;
-       }
-
-       die $USAGE;
+    ## Final output
+    ## These are meant to be compact and terse: sometimes messages go to pagers
+
+    $MRTG and do_mrtg_stats();
+
+    $action =~ s/^\s*(\S+)\s*$/$1/;
+    my $service = sprintf "%s$action", $FANCYNAME ? 'postgres_' : '';
+    if (keys %critical or keys %warning or keys %ok or keys %unknown) {
+        printf '%s ', $YELLNAME ? uc $service : $service;
+    }
+
+    sub dumpresult {
+        my ($type,$info) = @_;
+        my $SEP = ' * ';
+        ## Are we showing DEBUG_INFO?
+        my $showdebug = 0;
+        if ($DEBUGOUTPUT) {
+            $showdebug = 1 if $DEBUGOUTPUT =~ /a/io
+                or ($DEBUGOUTPUT =~ /c/io and $type eq 'c')
+                or ($DEBUGOUTPUT =~ /w/io and $type eq 'w')
+                or ($DEBUGOUTPUT =~ /o/io and $type eq 'o')
+                or ($DEBUGOUTPUT =~ /u/io and $type eq 'u');
+        }
+        for (sort keys %$info) {
+            printf "$_ %s%s ",
+                $showdebug ? "[DEBUG: $DEBUG_INFO] " : '',
+                join $SEP => map { $_->[0] } @{$info->{$_}};
+        }
+        if ($opt{showperf}) {
+            print '| ';
+            for (sort keys %$info) {
+                my $m = sprintf '%s ', join $SEP => map { $_->[1] } @{$info->{$_}};
+                if ($VERBOSE) {
+                    $m =~ s/  /\n/g;
+                }
+                print $m;
+            }
+        }
+        print "\n";
+    }
+
+    if (keys %critical) {
+        print 'CRITICAL: ';
+        dumpresult(c => \%critical);
+        exit 2;
+    }
+    if (keys %warning) {
+        print 'WARNING: ';
+        dumpresult(w => \%warning);
+        exit 1;
+    }
+    if (keys %ok) {
+        print 'OK: ';
+        dumpresult(o => \%ok);
+        exit 0;
+    }
+    if (keys %unknown) {
+        print 'UNKNOWN: ';
+        dumpresult(u => \%unknown);
+        exit 3;
+    }
+
+    die $USAGE;
 
 } ## end of finishup
 
@@ -1237,142 +1237,142 @@ our $checksumre = qr{^[a-f0-9]{32}$};
 
 ## If in test mode, verify that we can run each requested action
 our %testaction = (
-                                 autovac_freeze    => 'VERSION: 8.2',
-                                 last_vacuum       => 'ON: stats_row_level(<8.3) VERSION: 8.2',
-                                 last_analyze      => 'ON: stats_row_level(<8.3) VERSION: 8.2',
-                                 last_autovacuum   => 'ON: stats_row_level(<8.3) VERSION: 8.2',
-                                 last_autoanalyze  => 'ON: stats_row_level(<8.3) VERSION: 8.2',
-                                 prepared_txns     => 'VERSION: 8.1',
-                                 database_size     => 'VERSION: 8.1',
-                                 disabled_triggers => 'VERSION: 8.1',
-                                 relation_size     => 'VERSION: 8.1',
-                                 sequence          => 'VERSION: 8.1',
-                                 table_size        => 'VERSION: 8.1',
-                                 index_size        => 'VERSION: 8.1',
-                                 query_time        => 'ON: stats_command_string(<8.3) VERSION: 8.0',
-                                 txn_idle          => 'ON: stats_command_string(<8.3) VERSION: 8.0',
-                                 txn_time          => 'VERSION: 8.3',
-                                 wal_files         => 'VERSION: 8.1',
-                                 fsm_pages         => 'VERSION: 8.2 MAX: 8.3',
-                                 fsm_relations     => 'VERSION: 8.2 MAX: 8.3',
+                  autovac_freeze    => 'VERSION: 8.2',
+                  last_vacuum       => 'ON: stats_row_level(<8.3) VERSION: 8.2',
+                  last_analyze      => 'ON: stats_row_level(<8.3) VERSION: 8.2',
+                  last_autovacuum   => 'ON: stats_row_level(<8.3) VERSION: 8.2',
+                  last_autoanalyze  => 'ON: stats_row_level(<8.3) VERSION: 8.2',
+                  prepared_txns     => 'VERSION: 8.1',
+                  database_size     => 'VERSION: 8.1',
+                  disabled_triggers => 'VERSION: 8.1',
+                  relation_size     => 'VERSION: 8.1',
+                  sequence          => 'VERSION: 8.1',
+                  table_size        => 'VERSION: 8.1',
+                  index_size        => 'VERSION: 8.1',
+                  query_time        => 'ON: stats_command_string(<8.3) VERSION: 8.0',
+                  txn_idle          => 'ON: stats_command_string(<8.3) VERSION: 8.0',
+                  txn_time          => 'VERSION: 8.3',
+                  wal_files         => 'VERSION: 8.1',
+                  fsm_pages         => 'VERSION: 8.2 MAX: 8.3',
+                  fsm_relations     => 'VERSION: 8.2 MAX: 8.3',
 );
 if ($opt{test}) {
-       print msgn('testmode-start');
-       my $info = run_command('SELECT name, setting FROM pg_settings');
-       my %set; ## port, host, name, user
-       for my $db (@{$info->{db}}) {
-               if (exists $db->{fail}) {
-                       (my $err = $db->{error}) =~ s/\s*\n\s*/ \| /g;
-                       print msgn('testmode-fail', $db->{pname}, $err);
-                       next;
-               }
-               print msgn('testmode-ok', $db->{pname});
-               for (split /\n/ => $db->{slurp}) {
-                       while (/(\S+)\s*\|\s*(.+)\s*/sg) { ## no critic (ProhibitUnusedCapture)
-                               $set{$db->{pname}}{$1} = $2;
-                       }
-               }
-       }
-       for my $ac (split /\s+/ => $action) {
-               my $limit = $testaction{lc $ac};
-               next if ! defined $limit;
-
-               if ($limit =~ /VERSION: ((\d+)\.(\d+))/) {
-                       my ($rver,$rmaj,$rmin) = ($1,$2,$3);
-                       for my $db (@{$info->{db}}) {
-                               next unless exists $db->{ok};
-                               if ($set{$db->{pname}}{server_version} !~ /((\d+)\.(\d+))/) {
-                                       print msgn('testmode-nover', $db->{pname});
-                                       next;
-                               }
-                               my ($sver,$smaj,$smin) = ($1,$2,$3);
-                               if ($smaj < $rmaj or ($smaj==$rmaj and $smin < $rmin)) {
-                                       print msgn('testmode-norun', $ac, $db->{pname}, $rver, $sver);
-                               }
-                               $db->{version} = $sver;
-                       }
-               }
-
-               if ($limit =~ /MAX: ((\d+)\.(\d+))/) {
-                       my ($rver,$rmaj,$rmin) = ($1,$2,$3);
-                       for my $db (@{$info->{db}}) {
-                               next unless exists $db->{ok};
-                               if ($set{$db->{pname}}{server_version} !~ /((\d+)\.(\d+))/) {
-                                       print msgn('testmode-nover', $db->{pname});
-                                       next;
-                               }
-                               my ($sver,$smaj,$smin) = ($1,$2,$3);
-                               if ($smaj > $rmaj) {
-                                       print msgn('testmode-norun', $ac, $db->{pname}, $rver, $sver);
-                               }
-                       }
-               }
-
-               while ($limit =~ /\bON: (\w+)(?:\(([<>=])(\d+\.\d+)\))?/g) {
-                       my ($setting,$op,$ver) = ($1,$2||'',$3||0);
-                       for my $db (@{$info->{db}}) {
-                               next unless exists $db->{ok};
-                               if ($ver) {
-                                       next if $op eq '<' and $db->{version} >= $ver;
-                                       next if $op eq '>' and $db->{version} <= $ver;
-                                       next if $op eq '=' and $db->{version} != $ver;
-                               }
-                               my $val = $set{$db->{pname}}{$setting};
-                               if ($val ne 'on') {
-                                       print msgn('testmode-noset', $ac, $db->{pname}, $setting);
-                               }
-                       }
-               }
-       }
-       print msgn('testmode-end');
-       exit 0;
+    print msgn('testmode-start');
+    my $info = run_command('SELECT name, setting FROM pg_settings');
+    my %set; ## port, host, name, user
+    for my $db (@{$info->{db}}) {
+        if (exists $db->{fail}) {
+            (my $err = $db->{error}) =~ s/\s*\n\s*/ \| /g;
+            print msgn('testmode-fail', $db->{pname}, $err);
+            next;
+        }
+        print msgn('testmode-ok', $db->{pname});
+        for (split /\n/ => $db->{slurp}) {
+            while (/(\S+)\s*\|\s*(.+)\s*/sg) { ## no critic (ProhibitUnusedCapture)
+                $set{$db->{pname}}{$1} = $2;
+            }
+        }
+    }
+    for my $ac (split /\s+/ => $action) {
+        my $limit = $testaction{lc $ac};
+        next if ! defined $limit;
+
+        if ($limit =~ /VERSION: ((\d+)\.(\d+))/) {
+            my ($rver,$rmaj,$rmin) = ($1,$2,$3);
+            for my $db (@{$info->{db}}) {
+                next unless exists $db->{ok};
+                if ($set{$db->{pname}}{server_version} !~ /((\d+)\.(\d+))/) {
+                    print msgn('testmode-nover', $db->{pname});
+                    next;
+                }
+                my ($sver,$smaj,$smin) = ($1,$2,$3);
+                if ($smaj < $rmaj or ($smaj==$rmaj and $smin < $rmin)) {
+                    print msgn('testmode-norun', $ac, $db->{pname}, $rver, $sver);
+                }
+                $db->{version} = $sver;
+            }
+        }
+
+        if ($limit =~ /MAX: ((\d+)\.(\d+))/) {
+            my ($rver,$rmaj,$rmin) = ($1,$2,$3);
+            for my $db (@{$info->{db}}) {
+                next unless exists $db->{ok};
+                if ($set{$db->{pname}}{server_version} !~ /((\d+)\.(\d+))/) {
+                    print msgn('testmode-nover', $db->{pname});
+                    next;
+                }
+                my ($sver,$smaj,$smin) = ($1,$2,$3);
+                if ($smaj > $rmaj) {
+                    print msgn('testmode-norun', $ac, $db->{pname}, $rver, $sver);
+                }
+            }
+        }
+
+        while ($limit =~ /\bON: (\w+)(?:\(([<>=])(\d+\.\d+)\))?/g) {
+            my ($setting,$op,$ver) = ($1,$2||'',$3||0);
+            for my $db (@{$info->{db}}) {
+                next unless exists $db->{ok};
+                if ($ver) {
+                    next if $op eq '<' and $db->{version} >= $ver;
+                    next if $op eq '>' and $db->{version} <= $ver;
+                    next if $op eq '=' and $db->{version} != $ver;
+                }
+                my $val = $set{$db->{pname}}{$setting};
+                if ($val ne 'on') {
+                    print msgn('testmode-noset', $ac, $db->{pname}, $setting);
+                }
+            }
+        }
+    }
+    print msgn('testmode-end');
+    exit 0;
 }
 
 ## Expand the list of included/excluded users into a standard format
 our $USERWHERECLAUSE = '';
 if ($opt{includeuser}) {
-       my %userlist;
-       for my $user (@{$opt{includeuser}}) {
-               for my $u2 (split /,/ => $user) {
-                       $userlist{$u2}++;
-               }
-       }
-       my $safename;
-       if (1 == keys %userlist) {
-               ($safename = each %userlist) =~ s/'/''/g;
-               $USERWHERECLAUSE = " AND usename = '$safename'";
-       }
-       else {
-               $USERWHERECLAUSE = ' AND usename IN (';
-               for my $user (sort keys %userlist) {
-                       ($safename = $user) =~ s/'/''/g;
-                       $USERWHERECLAUSE .= "'$safename',";
-               }
-               chop $USERWHERECLAUSE;
-               $USERWHERECLAUSE .= ')';
-       }
+    my %userlist;
+    for my $user (@{$opt{includeuser}}) {
+        for my $u2 (split /,/ => $user) {
+            $userlist{$u2}++;
+        }
+    }
+    my $safename;
+    if (1 == keys %userlist) {
+        ($safename = each %userlist) =~ s/'/''/g;
+        $USERWHERECLAUSE = " AND usename = '$safename'";
+    }
+    else {
+        $USERWHERECLAUSE = ' AND usename IN (';
+        for my $user (sort keys %userlist) {
+            ($safename = $user) =~ s/'/''/g;
+            $USERWHERECLAUSE .= "'$safename',";
+        }
+        chop $USERWHERECLAUSE;
+        $USERWHERECLAUSE .= ')';
+    }
 }
 elsif ($opt{excludeuser}) {
-       my %userlist;
-       for my $user (@{$opt{excludeuser}}) {
-               for my $u2 (split /,/ => $user) {
-                       $userlist{$u2}++;
-               }
-       }
-       my $safename;
-       if (1 == keys %userlist) {
-               ($safename = each %userlist) =~ s/'/''/g;
-               $USERWHERECLAUSE = " AND usename <> '$safename'";
-       }
-       else {
-               $USERWHERECLAUSE = ' AND usename NOT IN (';
-               for my $user (sort keys %userlist) {
-                       ($safename = $user) =~ s/'/''/g;
-                       $USERWHERECLAUSE .= "'$safename',";
-               }
-               chop $USERWHERECLAUSE;
-               $USERWHERECLAUSE .= ')';
-       }
+    my %userlist;
+    for my $user (@{$opt{excludeuser}}) {
+        for my $u2 (split /,/ => $user) {
+            $userlist{$u2}++;
+        }
+    }
+    my $safename;
+    if (1 == keys %userlist) {
+        ($safename = each %userlist) =~ s/'/''/g;
+        $USERWHERECLAUSE = " AND usename <> '$safename'";
+    }
+    else {
+        $USERWHERECLAUSE = ' AND usename NOT IN (';
+        for my $user (sort keys %userlist) {
+            ($safename = $user) =~ s/'/''/g;
+            $USERWHERECLAUSE .= "'$safename',";
+        }
+        chop $USERWHERECLAUSE;
+        $USERWHERECLAUSE .= ')';
+    }
 }
 
 ## Check number of connections, compare to max_connections
@@ -1503,1045 +1503,1045 @@ exit 0;
 
 sub build_symlinks {
 
-       ## Create symlinks to most actions
-       $ME =~ /postgres/
-               or die msgn('symlink-name');
-
-       my $force = $action =~ /force/ ? 1 : 0;
-       for my $action (sort keys %$action_info) {
-               my $space = ' ' x ($longname - length $action);
-               my $file = "check_postgres_$action";
-               if (-l $file) {
-                       if (!$force) {
-                               my $source = readlink $file;
-                               print msgn('symlink-done', $file, $space, $source);
-                               next;
-                       }
-                       print msg('symlink-unlink', $file, $space);
-                       unlink $file or die msgn('symlink-fail1', $file, $!);
-               }
-               elsif (-e $file) {
-                       print msgn('symlink-exists', $file, $space);
-                       next;
-               }
-
-               if (symlink $0, $file) {
-                       print msgn('symlink-create', $file);
-               }
-               else {
-                       print msgn('symlink-fail2', $file, $ME, $!);
-               }
-       }
-
-       exit 0;
+    ## Create symlinks to most actions
+    $ME =~ /postgres/
+        or die msgn('symlink-name');
+
+    my $force = $action =~ /force/ ? 1 : 0;
+    for my $action (sort keys %$action_info) {
+        my $space = ' ' x ($longname - length $action);
+        my $file = "check_postgres_$action";
+        if (-l $file) {
+            if (!$force) {
+                my $source = readlink $file;
+                print msgn('symlink-done', $file, $space, $source);
+                next;
+            }
+            print msg('symlink-unlink', $file, $space);
+            unlink $file or die msgn('symlink-fail1', $file, $!);
+        }
+        elsif (-e $file) {
+            print msgn('symlink-exists', $file, $space);
+            next;
+        }
+
+        if (symlink $0, $file) {
+            print msgn('symlink-create', $file);
+        }
+        else {
+            print msgn('symlink-fail2', $file, $ME, $!);
+        }
+    }
+
+    exit 0;
 
 } ## end of build_symlinks
 
 
 sub pretty_size {
 
-       ## Transform number of bytes to a SI display similar to Postgres' format
+    ## Transform number of bytes to a SI display similar to Postgres' format
 
-       my $bytes = shift;
-       my $rounded = shift || 0;
+    my $bytes = shift;
+    my $rounded = shift || 0;
 
-       return "$bytes bytes" if $bytes < 10240;
+    return "$bytes bytes" if $bytes < 10240;
 
-       my @unit = qw/kB MB GB TB PB EB YB ZB/;
+    my @unit = qw/kB MB GB TB PB EB YB ZB/;
 
-       for my $p (1..@unit) {
-               if ($bytes <= 1024**$p) {
-                       $bytes /= (1024**($p-1));
-                       return $rounded ?
-                               sprintf ('%d %s', $bytes, $unit[$p-2]) :
-                                       sprintf ('%.2f %s', $bytes, $unit[$p-2]);
-               }
-       }
+    for my $p (1..@unit) {
+        if ($bytes <= 1024**$p) {
+            $bytes /= (1024**($p-1));
+            return $rounded ?
+                sprintf ('%d %s', $bytes, $unit[$p-2]) :
+                    sprintf ('%.2f %s', $bytes, $unit[$p-2]);
+        }
+    }
 
-       return $bytes;
+    return $bytes;
 
 } ## end of pretty_size
 
 
 sub pretty_time {
 
-       ## Transform number of seconds to a more human-readable format
-       ## First argument is number of seconds
-       ## Second optional arg is highest transform: s,m,h,d,w
-       ## If uppercase, it indicates to "round that one out"
-
-       my $sec = shift;
-       my $tweak = shift || '';
-
-       ## Just seconds (< 2:00)
-       if ($sec < 120 or $tweak =~ /s/) {
-               return sprintf "$sec %s", $sec==1 ? msg('time-second') : msg('time-seconds');
-       }
-
-       ## Minutes and seconds (< 60:00)
-       if ($sec < 60*60 or $tweak =~ /m/) {
-               my $min = int $sec / 60;
-               $sec %= 60;
-               my $ret = sprintf "$min %s", $min==1 ? msg('time-minute') : msg('time-minutes');
-               $sec and $tweak !~ /S/ and $ret .= sprintf " $sec %s", $sec==1 ? msg('time-second') : msg('time-seconds');
-               return $ret;
-       }
-
-       ## Hours, minutes, and seconds (< 48:00:00)
-       if ($sec < 60*60*24*2 or $tweak =~ /h/) {
-               my $hour = int $sec / (60*60);
-               $sec -= ($hour*60*60);
-               my $min = int $sec / 60;
-               $sec -= ($min*60);
-               my $ret = sprintf "$hour %s", $hour==1 ? msg('time-hour') : msg('time-hours');
-               $min and $tweak !~ /M/ and $ret .= sprintf " $min %s", $min==1 ? msg('time-minute') : msg('time-minutes');
-               $sec and $tweak !~ /[SM]/ and $ret .= sprintf " $sec %s", $sec==1 ? msg('time-second') : msg('time-seconds');
-               return $ret;
-       }
-
-       ## Days, hours, minutes, and seconds (< 28 days)
-       if ($sec < 60*60*24*28 or $tweak =~ /d/) {
-               my $day = int $sec / (60*60*24);
-               $sec -= ($day*60*60*24);
-               my $our = int $sec / (60*60);
-               $sec -= ($our*60*60);
-               my $min = int $sec / 60;
-               $sec -= ($min*60);
-               my $ret = sprintf "$day %s", $day==1 ? msg('time-day') : msg('time-days');
-               $our and $tweak !~ /H/     and $ret .= sprintf " $our %s", $our==1 ? msg('time-hour')   : msg('time-hours');
-               $min and $tweak !~ /[HM]/  and $ret .= sprintf " $min %s", $min==1 ? msg('time-minute') : msg('time-minutes');
-               $sec and $tweak !~ /[HMS]/ and $ret .= sprintf " $sec %s", $sec==1 ? msg('time-second') : msg('time-seconds');
-               return $ret;
-       }
-
-       ## Weeks, days, hours, minutes, and seconds (< 28 days)
-       my $week = int $sec / (60*60*24*7);
-       $sec -= ($week*60*60*24*7);
-       my $day = int $sec / (60*60*24);
-       $sec -= ($day*60*60*24);
-       my $our = int $sec / (60*60);
-       $sec -= ($our*60*60);
-       my $min = int $sec / 60;
-       $sec -= ($min*60);
-       my $ret = sprintf "$week %s", $week==1 ? msg('time-week') : msg('time-weeks');
-       $day and $tweak !~ /D/      and $ret .= sprintf " $day %s", $day==1 ? msg('time-day')    : msg('time-days');
-       $our and $tweak !~ /[DH]/   and $ret .= sprintf " $our %s", $our==1 ? msg('time-hour')   : msg('time-hours');
-       $min and $tweak !~ /[DHM]/  and $ret .= sprintf " $min %s", $min==1 ? msg('time-minute') : msg('time-minutes');
-       $sec and $tweak !~ /[DHMS]/ and $ret .= sprintf " $sec %s", $sec==1 ? msg('time-second') : msg('time-seconds');
-       return $ret;
+    ## Transform number of seconds to a more human-readable format
+    ## First argument is number of seconds
+    ## Second optional arg is highest transform: s,m,h,d,w
+    ## If uppercase, it indicates to "round that one out"
+
+    my $sec = shift;
+    my $tweak = shift || '';
+
+    ## Just seconds (< 2:00)
+    if ($sec < 120 or $tweak =~ /s/) {
+        return sprintf "$sec %s", $sec==1 ? msg('time-second') : msg('time-seconds');
+    }
+
+    ## Minutes and seconds (< 60:00)
+    if ($sec < 60*60 or $tweak =~ /m/) {
+        my $min = int $sec / 60;
+        $sec %= 60;
+        my $ret = sprintf "$min %s", $min==1 ? msg('time-minute') : msg('time-minutes');
+        $sec and $tweak !~ /S/ and $ret .= sprintf " $sec %s", $sec==1 ? msg('time-second') : msg('time-seconds');
+        return $ret;
+    }
+
+    ## Hours, minutes, and seconds (< 48:00:00)
+    if ($sec < 60*60*24*2 or $tweak =~ /h/) {
+        my $hour = int $sec / (60*60);
+        $sec -= ($hour*60*60);
+        my $min = int $sec / 60;
+        $sec -= ($min*60);
+        my $ret = sprintf "$hour %s", $hour==1 ? msg('time-hour') : msg('time-hours');
+        $min and $tweak !~ /M/ and $ret .= sprintf " $min %s", $min==1 ? msg('time-minute') : msg('time-minutes');
+        $sec and $tweak !~ /[SM]/ and $ret .= sprintf " $sec %s", $sec==1 ? msg('time-second') : msg('time-seconds');
+        return $ret;
+    }
+
+    ## Days, hours, minutes, and seconds (< 28 days)
+    if ($sec < 60*60*24*28 or $tweak =~ /d/) {
+        my $day = int $sec / (60*60*24);
+        $sec -= ($day*60*60*24);
+        my $our = int $sec / (60*60);
+        $sec -= ($our*60*60);
+        my $min = int $sec / 60;
+        $sec -= ($min*60);
+        my $ret = sprintf "$day %s", $day==1 ? msg('time-day') : msg('time-days');
+        $our and $tweak !~ /H/     and $ret .= sprintf " $our %s", $our==1 ? msg('time-hour')   : msg('time-hours');
+        $min and $tweak !~ /[HM]/  and $ret .= sprintf " $min %s", $min==1 ? msg('time-minute') : msg('time-minutes');
+        $sec and $tweak !~ /[HMS]/ and $ret .= sprintf " $sec %s", $sec==1 ? msg('time-second') : msg('time-seconds');
+        return $ret;
+    }
+
+    ## Weeks, days, hours, minutes, and seconds (< 28 days)
+    my $week = int $sec / (60*60*24*7);
+    $sec -= ($week*60*60*24*7);
+    my $day = int $sec / (60*60*24);
+    $sec -= ($day*60*60*24);
+    my $our = int $sec / (60*60);
+    $sec -= ($our*60*60);
+    my $min = int $sec / 60;
+    $sec -= ($min*60);
+    my $ret = sprintf "$week %s", $week==1 ? msg('time-week') : msg('time-weeks');
+    $day and $tweak !~ /D/      and $ret .= sprintf " $day %s", $day==1 ? msg('time-day')    : msg('time-days');
+    $our and $tweak !~ /[DH]/   and $ret .= sprintf " $our %s", $our==1 ? msg('time-hour')   : msg('time-hours');
+    $min and $tweak !~ /[DHM]/  and $ret .= sprintf " $min %s", $min==1 ? msg('time-minute') : msg('time-minutes');
+    $sec and $tweak !~ /[DHMS]/ and $ret .= sprintf " $sec %s", $sec==1 ? msg('time-second') : msg('time-seconds');
+    return $ret;
 
 } ## end of pretty_time
 
 
 sub run_command {
 
-       ## Run a command string against each of our databases using psql
-       ## Optional args in a hashref:
-       ## "failok" - don't report if we failed
-       ## "fatalregex" - allow this FATAL regex through
-       ## "target" - use this targetlist instead of generating one
-       ## "timeout" - change the timeout from the default of $opt{timeout}
-       ## "regex" - the query must match this or we throw an error
-       ## "emptyok" - it's okay to not match any rows at all
-       ## "version" - alternate versions for different versions
-       ## "dbnumber" - connect with an alternate set of params, e.g. port2 dbname2
-
-       my $string = shift || '';
-       my $arg = shift || {};
-       my $info = { command => $string, db => [], hosts => 0 };
-
-       $VERBOSE >= 3 and warn qq{Starting run_command with: $string\n};
-
-       my (%host,$passfile,$passfh,$tempdir,$tempfile,$tempfh,$errorfile,$errfh);
-       my $offset = -1;
-
-       ## Build a list of all databases to connect to.
-       ## Number is determined by host, port, and db arguments
-       ## Multi-args are grouped together: host, port, dbuser, dbpass
-       ## Grouped are kept together for first pass
-       ## The final arg in a group is passed on
-       ##
-       ## Examples:
-       ## --host=a,b --port=5433 --db=c
-       ## Connects twice to port 5433, using database c, to hosts a and b
-       ## a-5433-c b-5433-c
-       ##
-       ## --host=a,b --port=5433 --db=c,d
-       ## Connects four times: a-5433-c a-5433-d b-5433-c b-5433-d
-       ##
-       ## --host=a,b --host=foo --port=1234 --port=5433 --db=e,f
-       ## Connects six times: a-1234-e a-1234-f b-1234-e b-1234-f foo-5433-e foo-5433-f
-       ##
-       ## --host=a,b --host=x --port=5432,5433 --dbuser=alice --dbuser=bob -db=baz
-       ## Connects three times: a-5432-alice-baz b-5433-alice-baz x-5433-bob-baz
-
-       ## The final list of targets:
-       my @target;
-
-       ## Default connection options
-       my $conn =
-               {
-                host   =>    [$ENV{PGHOST}     || '<none>'],
-                port   =>    [$ENV{PGPORT}     || $opt{defaultport}],
-                dbname =>    [$ENV{PGDATABASE} || $opt{defaultdb}],
-                dbuser =>    [$ENV{PGUSER}     || $arg->{dbuser} || $opt{defaultuser}],
-                dbpass =>    [$ENV{PGPASSWORD} || ''],
-                dbservice => [''],
-                };
-
-       ## Don't set any default values if a service is being used
-       if (defined $opt{dbservice} and defined $opt{dbservice}->[0] and length $opt{dbservice}->[0]) {
-               $conn->{dbname} = [];
-               $conn->{port} = [];
-               $conn->{dbuser} = [];
-       }
-       my $gbin = 0;
-       GROUP: {
-               ## This level controls a "group" of targets
-
-               ## If we were passed in a target, use that and move on
-               if (exists $arg->{target}) {
-                       ## Make a copy, in case we are passed in a ref
-                       my $newtarget;
-                       for my $key (keys %$conn) {
-                               $newtarget->{$key} = exists $arg->{target}{$key} ? $arg->{target}{$key} : $conn->{$key};
-                       }
-                       push @target, $newtarget;
-                       last GROUP;
-               }
-
-               my %group;
-               my $foundgroup = 0;
-               for my $v (keys %$conn) {
-                       my $vname = $v;
-                       ## Something new?
-                       if ($arg->{dbnumber} and $arg->{dbnumber} ne '1') {
-                               $v .= "$arg->{dbnumber}";
-                       }
-                       if (defined $opt{$v}->[$gbin]) {
-                               my $new = $opt{$v}->[$gbin];
-                               $new =~ s/\s+//g unless $vname eq 'dbservice' or $vname eq 'host';
-                               ## Set this as the new default
-                               $conn->{$vname} = [split /,/ => $new];
-                               $foundgroup = 1;
-                       }
-                       $group{$vname} = $conn->{$vname};
-               }
-
-               last GROUP if ! $foundgroup and @target;
-
-               $gbin++;
-
-               ## Now break the newly created group into individual targets
-               my $tbin = 0;
-               TARGET: {
-                       my $foundtarget = 0;
-                       my %temptarget;
-                       for my $g (keys %group) {
-                               if (defined $group{$g}->[$tbin]) {
-                                       $conn->{$g} = [$group{$g}->[$tbin]];
-                                       $foundtarget = 1;
-                               }
-                               $temptarget{$g} = $conn->{$g}[0];
-                       }
-
-                       ## Leave if nothing new
-                       last TARGET if ! $foundtarget;
-
-                       ## Add to our master list
-                       push @target, \%temptarget;
-
-                       $tbin++;
-                       redo TARGET;
-               } ## end TARGET
-
-               last GROUP if ! $foundgroup;
-               redo GROUP;
-       } ## end GROUP
-
-       if (! @target) {
-               ndie msg('runcommand-nodb');
-       }
-
-       ## Create a temp file to store our results
-       my @tempdirargs = (CLEANUP => 1);
-       if ($opt{tempdir}) {
-               push @tempdirargs => 'DIR', $opt{tempdir};
-       }
-       $tempdir = tempdir(@tempdirargs);
-       ($tempfh,$tempfile) = tempfile('check_postgres_psql.XXXXXXX', SUFFIX => '.tmp', DIR => $tempdir);
-
-       ## Create another one to catch any errors
-       ($errfh,$errorfile) = tempfile('check_postgres_psql_stderr.XXXXXXX', SUFFIX => '.tmp', DIR => $tempdir);
-
-       for $db (@target) {
-
-               ## Just to keep things clean:
-               truncate $tempfh, 0;
-               truncate $errfh, 0;
-
-               ## Store this target in the global target list
-               push @{$info->{db}}, $db;
-
-               my @args = ('-q', '-t');
-               if (defined $db->{dbservice} and length $db->{dbservice}) { ## XX Check for simple names
-                       $db->{pname} = "service=$db->{dbservice}";
-                       $ENV{PGSERVICE} = $db->{dbservice};
-               }
-               else {
-                       $db->{pname} = "port=$db->{port} host=$db->{host} db=$db->{dbname} user=$db->{dbuser}";
-               }
-               defined $db->{dbname} and push @args, '-d', $db->{dbname};
-               defined $db->{dbuser} and push @args, '-U', $db->{dbuser};
-               defined $db->{port} and push @args => '-p', $db->{port};
-               if ($db->{host} ne '<none>') {
-                       push @args => '-h', $db->{host};
-                       $host{$db->{host}}++; ## For the overall count
-               }
-
-               if (defined $db->{dbpass} and length $db->{dbpass}) {
-                       ## Make a custom PGPASSFILE. Far better to simply use your own .pgpass of course
-                       ($passfh,$passfile) = tempfile('check_postgres.XXXXXXXX', SUFFIX => '.tmp', DIR => $tempdir);
-                       $VERBOSE >= 3 and warn msgn('runcommand-pgpass', $passfile);
-                       $ENV{PGPASSFILE} = $passfile;
-                       printf $passfh "%s:%s:%s:%s:%s\n",
-                               $db->{host} eq '<none>' ? '*' : $db->{host}, $db->{port}, $db->{dbname}, $db->{dbuser}, $db->{dbpass};
-                       close $passfh or ndie msg('file-noclose', $passfile, $!);
-               }
-
-               push @args, '-o', $tempfile;
-               push @args => '-x';
-
-               ## If we've got different SQL, use this first run to simply grab the version
-               ## Then we'll use that info to pick the real query
-               if ($arg->{version}) {
-                       if (!$db->{version}) {
-                               $arg->{versiononly} = 1;
-                               $arg->{oldstring} = $string;
-                               $string = 'SELECT version()';
-                       }
-                       else {
-                               $string = $arg->{oldstring} || $arg->{string};
-                               for my $row (@{$arg->{version}}) {
-                                       if ($row !~ s/^([<>]?)(\d+\.\d+)\s+//) {
-                                               ndie msg('die-badversion', $row);
-                                       }
-                                       my ($mod,$ver) = ($1||'',$2);
-                                       if ($mod eq '>' and $db->{version} > $ver) {
-                                               $string = $row;
-                                               last;
-                                       }
-                                       if ($mod eq '<' and $db->{version} < $ver) {
-                                               $string = $row;
-                                               last;
-                                       }
-                                       if ($mod eq '' and $db->{version} eq $ver) {
-                                               $string = $row;
-                                       }
-                               }
-                               delete $arg->{version};
-                               $info->{command} = $string;
-                       }
-               }
-
-               local $SIG{ALRM} = sub { die 'Timed out' };
-               my $timeout = $arg->{timeout} || $opt{timeout};
-               my $dbtimeout = $timeout * 1000;
-               alarm 0;
-
-               if ($action ne 'pgbouncer_checksum') {
-                       $string = "BEGIN;SET statement_timeout=$dbtimeout;COMMIT;$string";
-               }
-
-               push @args, '-c', $string;
-
-               $VERBOSE >= 3 and warn Dumper \@args;
-
-               my $start = $opt{showtime} ? [gettimeofday()] : 0;
-               open my $oldstderr, '>&', \*STDERR or ndie msg('runcommand-nodupe');
-               open STDERR, '>', $errorfile or ndie msg('runcommand-noerr');
-               eval {
-                       alarm $timeout;
-                       $res = system $PSQL => @args;
-               };
-               my $err = $@;
-               alarm 0;
-               open STDERR, '>&', $oldstderr or ndie msg('runcommand-noerr');
-               close $oldstderr or ndie msg('file-noclose', 'STDERR copy', $!);
-               if ($err) {
-                       if ($err =~ /Timed out/) {
-                               ndie msg('runcommand-timeout', $timeout);
-                       }
-                       else {
-                               ndie msg('runcommand-err');
-                       }
-               }
-
-               $db->{totaltime} = sprintf '%.2f', $opt{showtime} ? tv_interval($start) : 0;
-
-               if ($res) {
-                       $db->{fail} = $res;
-                       $VERBOSE >= 3 and !$arg->{failok} and warn msgn('runcommand-nosys', $res);
-                       seek $errfh, 0, 0;
-                       {
-                               local $/;
-                               $db->{error} = <$errfh> || '';
-                               $db->{error} =~ s/\s*$//;
-                               $db->{error} =~ s/^psql: //;
-                               $ERROR = $db->{error};
-                       }
-
-                       if ($db->{error} =~ /FATAL/) {
-                               if (exists $arg->{fatalregex} and $db->{error} =~ /$arg->{fatalregex}/) {
-                                       $info->{fatalregex} = $db->{error};
-                                       next;
-                               }
-                               else {
-                                       ndie "$db->{error}";
-                               }
-                       }
-
-                       elsif ($db->{error} =~ /statement timeout/) {
-                               ndie msg('runcommand-timeout', $timeout);
-                       }
-
-                       if (!$db->{ok} and !$arg->{failok} and !$arg->{noverify}) {
-
-                               ## Check if problem is due to backend being too old for this check
-                               verify_version();
-
-                               if (exists $db->{error}) {
-                                       ndie $db->{error};
-                               }
-
-                               add_unknown;
-                               ## Remove it from the returned hash
-                               pop @{$info->{db}};
-                       }
-               }
-               else {
-                       seek $tempfh, 0, 0;
-                       {
-                               local $/;
-                               $db->{slurp} = <$tempfh>;
-                       }
-                       $db->{ok} = 1;
-
-                       ## Unfortunately, psql outputs "(No rows)" even with -t and -x
-                       $db->{slurp} = '' if index($db->{slurp},'(')==0;
-
-                       ## Allow an empty query (no matching rows) if requested
-                       if ($arg->{emptyok} and $db->{slurp} =~ /^\s*$/o) {
-                               $arg->{emptyok2} = 1;
-                       }
-                       ## If we just want a version, grab it and redo
-                       if ($arg->{versiononly}) {
-                               if ($db->{error}) {
-                                       ndie $db->{error};
-                               }
-                               if ($db->{slurp} !~ /PostgreSQL (\d+\.\d+)/) {
-                                       ndie msg('die-badversion', $db->{slurp});
-                               }
-                               $db->{version} = $1;
-                               $db->{ok} = 0;
-                               delete $arg->{versiononly};
-                               ## Remove this from the returned hash
-                               pop @{$info->{db}};
-                               redo;
-                       }
-
-                       ## If we were provided with a regex, check and bail if it fails
-                       if ($arg->{regex} and ! $arg->{emptyok2}) {
-                               if ($db->{slurp} !~ $arg->{regex}) {
-                                       ## Check if problem is due to backend being too old for this check
-
-                                       verify_version();
-
-                                       add_unknown msg('invalid-query', $db->{slurp});
-
-                                       finishup();
-                                       exit 0;
-                               }
-                       }
-
-                       ## Transform psql output into an arrayref of hashes
-                       my @stuff;
-                       my $num = 0;
-                       my $lastval;
-                       for my $line (split /\n/ => $db->{slurp}) {
-                               if (index($line,'-')==0) {
-                                       $num++;
-                                       next;
-                               }
-                               if ($line =~ /^(\w+)\s+\| (.*)/) {
-                                       $stuff[$num]{$1} = $2;
-                                       $lastval = $1;
-                               }
-                               elsif ($line =~ /^QUERY PLAN\s+\| (.*)/) {
-                                       $stuff[$num]{queryplan} = $1;
-                                       $lastval = 'queryplan';
-                               }
-                               elsif ($line =~ /^\s+: (.*)/) {
-                                       $stuff[$num]{$lastval} .= "\n$1";
-                               }
-                               else {
-                                       ### XXX msg these
-                                       warn "Could not parse psql output!\n";
-                                       warn "Please report these details to check_postgres\@bucardo.org:\n";
-                                       my $cline = (caller)[2];
-                                       my $args = join ' ' => @args;
-                                       warn "Version:      $VERSION\n";
-                                       warn "Action:       $action\n";
-                                       warn "Calling line: $cline\n";
-                                       warn "Output:       $line\n";
-                                       warn "Command:      $PSQL $args\n";
-                                       exit 1;
-                               }
-                       }
-                       $db->{slurp} = \@stuff;
-
-               } ## end valid system call
-
-
-       } ## end each database
-
-       close $errfh or ndie msg('file-noclose', $errorfile, $!);
-       close $tempfh or ndie msg('file-noclose', $tempfile, $!);
-
-       eval { File::Temp::cleanup(); };
-
-       $info->{hosts} = keys %host;
-
-       $VERBOSE >= 3 and warn Dumper $info;
-
-       if ($DEBUGOUTPUT) {
-               if (defined $info->{db} and defined $info->{db}[0]{slurp}) {
-                       $DEBUG_INFO = $info->{db}[0]{slurp};
-                       $DEBUG_INFO =~ s/\n/\\n/g;
-                       $DEBUG_INFO =~ s/\|/<SEP>/g;
-               }
-       }
-
-       return $info;
+    ## Run a command string against each of our databases using psql
+    ## Optional args in a hashref:
+    ## "failok" - don't report if we failed
+    ## "fatalregex" - allow this FATAL regex through
+    ## "target" - use this targetlist instead of generating one
+    ## "timeout" - change the timeout from the default of $opt{timeout}
+    ## "regex" - the query must match this or we throw an error
+    ## "emptyok" - it's okay to not match any rows at all
+    ## "version" - alternate versions for different versions
+    ## "dbnumber" - connect with an alternate set of params, e.g. port2 dbname2
+
+    my $string = shift || '';
+    my $arg = shift || {};
+    my $info = { command => $string, db => [], hosts => 0 };
+
+    $VERBOSE >= 3 and warn qq{Starting run_command with: $string\n};
+
+    my (%host,$passfile,$passfh,$tempdir,$tempfile,$tempfh,$errorfile,$errfh);
+    my $offset = -1;
+
+    ## Build a list of all databases to connect to.
+    ## Number is determined by host, port, and db arguments
+    ## Multi-args are grouped together: host, port, dbuser, dbpass
+    ## Grouped are kept together for first pass
+    ## The final arg in a group is passed on
+    ##
+    ## Examples:
+    ## --host=a,b --port=5433 --db=c
+    ## Connects twice to port 5433, using database c, to hosts a and b
+    ## a-5433-c b-5433-c
+    ##
+    ## --host=a,b --port=5433 --db=c,d
+    ## Connects four times: a-5433-c a-5433-d b-5433-c b-5433-d
+    ##
+    ## --host=a,b --host=foo --port=1234 --port=5433 --db=e,f
+    ## Connects six times: a-1234-e a-1234-f b-1234-e b-1234-f foo-5433-e foo-5433-f
+    ##
+    ## --host=a,b --host=x --port=5432,5433 --dbuser=alice --dbuser=bob -db=baz
+    ## Connects three times: a-5432-alice-baz b-5433-alice-baz x-5433-bob-baz
+
+    ## The final list of targets:
+    my @target;
+
+    ## Default connection options
+    my $conn =
+        {
+         host   =>    [$ENV{PGHOST}     || '<none>'],
+         port   =>    [$ENV{PGPORT}     || $opt{defaultport}],
+         dbname =>    [$ENV{PGDATABASE} || $opt{defaultdb}],
+         dbuser =>    [$ENV{PGUSER}     || $arg->{dbuser} || $opt{defaultuser}],
+         dbpass =>    [$ENV{PGPASSWORD} || ''],
+         dbservice => [''],
+         };
+
+    ## Don't set any default values if a service is being used
+    if (defined $opt{dbservice} and defined $opt{dbservice}->[0] and length $opt{dbservice}->[0]) {
+        $conn->{dbname} = [];
+        $conn->{port} = [];
+        $conn->{dbuser} = [];
+    }
+    my $gbin = 0;
+    GROUP: {
+        ## This level controls a "group" of targets
+
+        ## If we were passed in a target, use that and move on
+        if (exists $arg->{target}) {
+            ## Make a copy, in case we are passed in a ref
+            my $newtarget;
+            for my $key (keys %$conn) {
+                $newtarget->{$key} = exists $arg->{target}{$key} ? $arg->{target}{$key} : $conn->{$key};
+            }
+            push @target, $newtarget;
+            last GROUP;
+        }
+
+        my %group;
+        my $foundgroup = 0;
+        for my $v (keys %$conn) {
+            my $vname = $v;
+            ## Something new?
+            if ($arg->{dbnumber} and $arg->{dbnumber} ne '1') {
+                $v .= "$arg->{dbnumber}";
+            }
+            if (defined $opt{$v}->[$gbin]) {
+                my $new = $opt{$v}->[$gbin];
+                $new =~ s/\s+//g unless $vname eq 'dbservice' or $vname eq 'host';
+                ## Set this as the new default
+                $conn->{$vname} = [split /,/ => $new];
+                $foundgroup = 1;
+            }
+            $group{$vname} = $conn->{$vname};
+        }
+
+        last GROUP if ! $foundgroup and @target;
+
+        $gbin++;
+
+        ## Now break the newly created group into individual targets
+        my $tbin = 0;
+        TARGET: {
+            my $foundtarget = 0;
+            my %temptarget;
+            for my $g (keys %group) {
+                if (defined $group{$g}->[$tbin]) {
+                    $conn->{$g} = [$group{$g}->[$tbin]];
+                    $foundtarget = 1;
+                }
+                $temptarget{$g} = $conn->{$g}[0];
+            }
+
+            ## Leave if nothing new
+            last TARGET if ! $foundtarget;
+
+            ## Add to our master list
+            push @target, \%temptarget;
+
+            $tbin++;
+            redo TARGET;
+        } ## end TARGET
+
+        last GROUP if ! $foundgroup;
+        redo GROUP;
+    } ## end GROUP
+
+    if (! @target) {
+        ndie msg('runcommand-nodb');
+    }
+
+    ## Create a temp file to store our results
+    my @tempdirargs = (CLEANUP => 1);
+    if ($opt{tempdir}) {
+        push @tempdirargs => 'DIR', $opt{tempdir};
+    }
+    $tempdir = tempdir(@tempdirargs);
+    ($tempfh,$tempfile) = tempfile('check_postgres_psql.XXXXXXX', SUFFIX => '.tmp', DIR => $tempdir);
+
+    ## Create another one to catch any errors
+    ($errfh,$errorfile) = tempfile('check_postgres_psql_stderr.XXXXXXX', SUFFIX => '.tmp', DIR => $tempdir);
+
+    for $db (@target) {
+
+        ## Just to keep things clean:
+        truncate $tempfh, 0;
+        truncate $errfh, 0;
+
+        ## Store this target in the global target list
+        push @{$info->{db}}, $db;
+
+        my @args = ('-q', '-t');
+        if (defined $db->{dbservice} and length $db->{dbservice}) { ## XX Check for simple names
+            $db->{pname} = "service=$db->{dbservice}";
+            $ENV{PGSERVICE} = $db->{dbservice};
+        }
+        else {
+            $db->{pname} = "port=$db->{port} host=$db->{host} db=$db->{dbname} user=$db->{dbuser}";
+        }
+        defined $db->{dbname} and push @args, '-d', $db->{dbname};
+        defined $db->{dbuser} and push @args, '-U', $db->{dbuser};
+        defined $db->{port} and push @args => '-p', $db->{port};
+        if ($db->{host} ne '<none>') {
+            push @args => '-h', $db->{host};
+            $host{$db->{host}}++; ## For the overall count
+        }
+
+        if (defined $db->{dbpass} and length $db->{dbpass}) {
+            ## Make a custom PGPASSFILE. Far better to simply use your own .pgpass of course
+            ($passfh,$passfile) = tempfile('check_postgres.XXXXXXXX', SUFFIX => '.tmp', DIR => $tempdir);
+            $VERBOSE >= 3 and warn msgn('runcommand-pgpass', $passfile);
+            $ENV{PGPASSFILE} = $passfile;
+            printf $passfh "%s:%s:%s:%s:%s\n",
+                $db->{host} eq '<none>' ? '*' : $db->{host}, $db->{port}, $db->{dbname}, $db->{dbuser}, $db->{dbpass};
+            close $passfh or ndie msg('file-noclose', $passfile, $!);
+        }
+
+        push @args, '-o', $tempfile;
+        push @args => '-x';
+
+        ## If we've got different SQL, use this first run to simply grab the version
+        ## Then we'll use that info to pick the real query
+        if ($arg->{version}) {
+            if (!$db->{version}) {
+                $arg->{versiononly} = 1;
+                $arg->{oldstring} = $string;
+                $string = 'SELECT version()';
+            }
+            else {
+                $string = $arg->{oldstring} || $arg->{string};
+                for my $row (@{$arg->{version}}) {
+                    if ($row !~ s/^([<>]?)(\d+\.\d+)\s+//) {
+                        ndie msg('die-badversion', $row);
+                    }
+                    my ($mod,$ver) = ($1||'',$2);
+                    if ($mod eq '>' and $db->{version} > $ver) {
+                        $string = $row;
+                        last;
+                    }
+                    if ($mod eq '<' and $db->{version} < $ver) {
+                        $string = $row;
+                        last;
+                    }
+                    if ($mod eq '' and $db->{version} eq $ver) {
+                        $string = $row;
+                    }
+                }
+                delete $arg->{version};
+                $info->{command} = $string;
+            }
+        }
+
+        local $SIG{ALRM} = sub { die 'Timed out' };
+        my $timeout = $arg->{timeout} || $opt{timeout};
+        my $dbtimeout = $timeout * 1000;
+        alarm 0;
+
+        if ($action ne 'pgbouncer_checksum') {
+            $string = "BEGIN;SET statement_timeout=$dbtimeout;COMMIT;$string";
+        }
+
+        push @args, '-c', $string;
+
+        $VERBOSE >= 3 and warn Dumper \@args;
+
+        my $start = $opt{showtime} ? [gettimeofday()] : 0;
+        open my $oldstderr, '>&', \*STDERR or ndie msg('runcommand-nodupe');
+        open STDERR, '>', $errorfile or ndie msg('runcommand-noerr');
+        eval {
+            alarm $timeout;
+            $res = system $PSQL => @args;
+        };
+        my $err = $@;
+        alarm 0;
+        open STDERR, '>&', $oldstderr or ndie msg('runcommand-noerr');
+        close $oldstderr or ndie msg('file-noclose', 'STDERR copy', $!);
+        if ($err) {
+            if ($err =~ /Timed out/) {
+                ndie msg('runcommand-timeout', $timeout);
+            }
+            else {
+                ndie msg('runcommand-err');
+            }
+        }
+
+        $db->{totaltime} = sprintf '%.2f', $opt{showtime} ? tv_interval($start) : 0;
+
+        if ($res) {
+            $db->{fail} = $res;
+            $VERBOSE >= 3 and !$arg->{failok} and warn msgn('runcommand-nosys', $res);
+            seek $errfh, 0, 0;
+            {
+                local $/;
+                $db->{error} = <$errfh> || '';
+                $db->{error} =~ s/\s*$//;
+                $db->{error} =~ s/^psql: //;
+                $ERROR = $db->{error};
+            }
+
+            if ($db->{error} =~ /FATAL/) {
+                if (exists $arg->{fatalregex} and $db->{error} =~ /$arg->{fatalregex}/) {
+                    $info->{fatalregex} = $db->{error};
+                    next;
+                }
+                else {
+                    ndie "$db->{error}";
+                }
+            }
+
+            elsif ($db->{error} =~ /statement timeout/) {
+                ndie msg('runcommand-timeout', $timeout);
+            }
+
+            if (!$db->{ok} and !$arg->{failok} and !$arg->{noverify}) {
+
+                ## Check if problem is due to backend being too old for this check
+                verify_version();
+
+                if (exists $db->{error}) {
+                    ndie $db->{error};
+                }
+
+                add_unknown;
+                ## Remove it from the returned hash
+                pop @{$info->{db}};
+            }
+        }
+        else {
+            seek $tempfh, 0, 0;
+            {
+                local $/;
+                $db->{slurp} = <$tempfh>;
+            }
+            $db->{ok} = 1;
+
+            ## Unfortunately, psql outputs "(No rows)" even with -t and -x
+            $db->{slurp} = '' if index($db->{slurp},'(')==0;
+
+            ## Allow an empty query (no matching rows) if requested
+            if ($arg->{emptyok} and $db->{slurp} =~ /^\s*$/o) {
+                $arg->{emptyok2} = 1;
+            }
+            ## If we just want a version, grab it and redo
+            if ($arg->{versiononly}) {
+                if ($db->{error}) {
+                    ndie $db->{error};
+                }
+                if ($db->{slurp} !~ /PostgreSQL (\d+\.\d+)/) {
+                    ndie msg('die-badversion', $db->{slurp});
+                }
+                $db->{version} = $1;
+                $db->{ok} = 0;
+                delete $arg->{versiononly};
+                ## Remove this from the returned hash
+                pop @{$info->{db}};
+                redo;
+            }
+
+            ## If we were provided with a regex, check and bail if it fails
+            if ($arg->{regex} and ! $arg->{emptyok2}) {
+                if ($db->{slurp} !~ $arg->{regex}) {
+                    ## Check if problem is due to backend being too old for this check
+
+                    verify_version();
+
+                    add_unknown msg('invalid-query', $db->{slurp});
+
+                    finishup();
+                    exit 0;
+                }
+            }
+
+            ## Transform psql output into an arrayref of hashes
+            my @stuff;
+            my $num = 0;
+            my $lastval;
+            for my $line (split /\n/ => $db->{slurp}) {
+                if (index($line,'-')==0) {
+                    $num++;
+                    next;
+                }
+                if ($line =~ /^(\w+)\s+\| (.*)/) {
+                    $stuff[$num]{$1} = $2;
+                    $lastval = $1;
+                }
+                elsif ($line =~ /^QUERY PLAN\s+\| (.*)/) {
+                    $stuff[$num]{queryplan} = $1;
+                    $lastval = 'queryplan';
+                }
+                elsif ($line =~ /^\s+: (.*)/) {
+                    $stuff[$num]{$lastval} .= "\n$1";
+                }
+                else {
+                    ### XXX msg these
+                    warn "Could not parse psql output!\n";
+                    warn "Please report these details to check_postgres\@bucardo.org:\n";
+                    my $cline = (caller)[2];
+                    my $args = join ' ' => @args;
+                    warn "Version:      $VERSION\n";
+                    warn "Action:       $action\n";
+                    warn "Calling line: $cline\n";
+                    warn "Output:       $line\n";
+                    warn "Command:      $PSQL $args\n";
+                    exit 1;
+                }
+            }
+            $db->{slurp} = \@stuff;
+
+        } ## end valid system call
+
+
+    } ## end each database
+
+    close $errfh or ndie msg('file-noclose', $errorfile, $!);
+    close $tempfh or ndie msg('file-noclose', $tempfile, $!);
+
+    eval { File::Temp::cleanup(); };
+
+    $info->{hosts} = keys %host;
+
+    $VERBOSE >= 3 and warn Dumper $info;
+
+    if ($DEBUGOUTPUT) {
+        if (defined $info->{db} and defined $info->{db}[0]{slurp}) {
+            $DEBUG_INFO = $info->{db}[0]{slurp};
+            $DEBUG_INFO =~ s/\n/\\n/g;
+            $DEBUG_INFO =~ s/\|/<SEP>/g;
+        }
+    }
+
+    return $info;
 
 } ## end of run_command
 
 
 sub verify_version {
 
-       ## Check if the backend can handle the current action
-       my $limit = $testaction{lc $action} || '';
-
-       my $versiononly = shift || 0;
-
-       return if ! $limit and ! $versiononly;
-
-       ## We almost always need the version, so just grab it for any limitation
-       $SQL = q{SELECT setting FROM pg_settings WHERE name = 'server_version'};
-       my $oldslurp = $db->{slurp} || '';
-       my $info = run_command($SQL, {noverify => 1});
-       if (defined $info->{db}[0]
-               and exists $info->{db}[0]{error}
-               and defined $info->{db}[0]{error}
-               ) {
-               ndie $info->{db}[0]{error};
-       }
-
-       if (!defined $info->{db}[0] or $info->{db}[0]{slurp}[0]{setting} !~ /((\d+)\.(\d+))/) {
-               ndie msg('die-badversion', $SQL);
-       }
-       my ($sver,$smaj,$smin) = ($1,$2,$3);
-
-       if ($versiononly) {
-               return $sver;
-       }
-
-       if ($limit =~ /VERSION: ((\d+)\.(\d+))/) {
-               my ($rver,$rmaj,$rmin) = ($1,$2,$3);
-               if ($smaj < $rmaj or ($smaj==$rmaj and $smin < $rmin)) {
-                       ndie msg('die-action-version', $action, $rver, $sver);
-               }
-       }
-
-       while ($limit =~ /\bON: (\w+)(?:\(([<>=])(\d+\.\d+)\))?/g) {
-               my ($setting,$op,$ver) = ($1,$2||'',$3||0);
-               if ($ver) {
-                       next if $op eq '<' and $sver >= $ver;
-                       next if $op eq '>' and $sver <= $ver;
-                       next if $op eq '=' and $sver != $ver;
-               }
-
-               $SQL = qq{SELECT setting FROM pg_settings WHERE name = '$setting'};
-               my $info2 = run_command($SQL);
-               if (!defined $info2->{db}[0]) {
-                       ndie msg('die-nosetting', $setting);
-               }
-               my $val = $info2->{db}[0]{slurp};
-               if ($val !~ /^\s*on\b/) {
-                       ndie msg('die-noset', $action, $setting);
-               }
-       }
-
-       $db->{slurp} = $oldslurp;
-       return;
+    ## Check if the backend can handle the current action
+    my $limit = $testaction{lc $action} || '';
+
+    my $versiononly = shift || 0;
+
+    return if ! $limit and ! $versiononly;
+
+    ## We almost always need the version, so just grab it for any limitation
+    $SQL = q{SELECT setting FROM pg_settings WHERE name = 'server_version'};
+    my $oldslurp = $db->{slurp} || '';
+    my $info = run_command($SQL, {noverify => 1});
+    if (defined $info->{db}[0]
+        and exists $info->{db}[0]{error}
+        and defined $info->{db}[0]{error}
+        ) {
+        ndie $info->{db}[0]{error};
+    }
+
+    if (!defined $info->{db}[0] or $info->{db}[0]{slurp}[0]{setting} !~ /((\d+)\.(\d+))/) {
+        ndie msg('die-badversion', $SQL);
+    }
+    my ($sver,$smaj,$smin) = ($1,$2,$3);
+
+    if ($versiononly) {
+        return $sver;
+    }
+
+    if ($limit =~ /VERSION: ((\d+)\.(\d+))/) {
+        my ($rver,$rmaj,$rmin) = ($1,$2,$3);
+        if ($smaj < $rmaj or ($smaj==$rmaj and $smin < $rmin)) {
+            ndie msg('die-action-version', $action, $rver, $sver);
+        }
+    }
+
+    while ($limit =~ /\bON: (\w+)(?:\(([<>=])(\d+\.\d+)\))?/g) {
+        my ($setting,$op,$ver) = ($1,$2||'',$3||0);
+        if ($ver) {
+            next if $op eq '<' and $sver >= $ver;
+            next if $op eq '>' and $sver <= $ver;
+            next if $op eq '=' and $sver != $ver;
+        }
+
+        $SQL = qq{SELECT setting FROM pg_settings WHERE name = '$setting'};
+        my $info2 = run_command($SQL);
+        if (!defined $info2->{db}[0]) {
+            ndie msg('die-nosetting', $setting);
+        }
+        my $val = $info2->{db}[0]{slurp};
+        if ($val !~ /^\s*on\b/) {
+            ndie msg('die-noset', $action, $setting);
+        }
+    }
+
+    $db->{slurp} = $oldslurp;
+    return;
 
 } ## end of verify_version
 
 
 sub size_in_bytes { ## no critic (RequireArgUnpacking)
 
-       ## Given a number and a unit, return the number of bytes.
-       ## Defaults to bytes
+    ## Given a number and a unit, return the number of bytes.
+    ## Defaults to bytes
 
-       my ($val,$unit) = ($_[0],lc substr($_[1]||'s',0,1));
-       return $val * ($unit eq 'b' ? 1 : $unit eq 'k' ? 1024 : $unit eq 'm' ? 1024**2 :
-                                       $unit eq 'g' ? 1024**3 : $unit eq 't' ? 1024**4 :
-                                       $unit eq 'p' ? 1024**5 : $unit eq 'e' ? 1024**6 :
-                                       $unit eq 'z' ? 1024**7 : 1);
+    my ($val,$unit) = ($_[0],lc substr($_[1]||'s',0,1));
+    return $val * ($unit eq 'b' ? 1 : $unit eq 'k' ? 1024 : $unit eq 'm' ? 1024**2 :
+                    $unit eq 'g' ? 1024**3 : $unit eq 't' ? 1024**4 :
+                    $unit eq 'p' ? 1024**5 : $unit eq 'e' ? 1024**6 :
+                    $unit eq 'z' ? 1024**7 : 1);
 
 } ## end of size_in_bytes
 
 
 sub size_in_seconds {
 
-       my ($string,$type) = @_;
-
-       return '' if ! length $string;
-       if ($string !~ $timere) {
-               ndie msg('die-badtime', $type, substr($type,0,1));
-       }
-       my ($val,$unit) = ($1,lc substr($2||'s',0,1));
-       my $tempval = sprintf '%.9f', $val * (
-               $unit eq 's' ?        1 :
-               $unit eq 'm' ?       60 :
-               $unit eq 'h' ?     3600 :
-               $unit eq 'd' ?    86400 :
-               $unit eq 'w' ?   604800 :
-               $unit eq 'y' ? 31536000 :
-                       ndie msg('die-badtime', $type, substr($type,0,1))
-       );
-       $tempval =~ s/0+$//;
-       $tempval = int $tempval if $tempval =~ /\.$/;
-       return $tempval;
+    my ($string,$type) = @_;
+
+    return '' if ! length $string;
+    if ($string !~ $timere) {
+        ndie msg('die-badtime', $type, substr($type,0,1));
+    }
+    my ($val,$unit) = ($1,lc substr($2||'s',0,1));
+    my $tempval = sprintf '%.9f', $val * (
+        $unit eq 's' ?        1 :
+        $unit eq 'm' ?       60 :
+        $unit eq 'h' ?     3600 :
+        $unit eq 'd' ?    86400 :
+        $unit eq 'w' ?   604800 :
+        $unit eq 'y' ? 31536000 :
+            ndie msg('die-badtime', $type, substr($type,0,1))
+    );
+    $tempval =~ s/0+$//;
+    $tempval = int $tempval if $tempval =~ /\.$/;
+    return $tempval;
 
 } ## end of size_in_seconds
 
 
 sub skip_item {
 
-       ## Determine if something should be skipped due to inclusion/exclusion options
-       ## Exclusion checked first: inclusion can pull it back in.
-       my $name = shift;
-       my $schema = shift || '';
-
-       my $stat = 0;
-       ## Is this excluded?
-       if (defined $opt{exclude}) {
-               $stat = 1;
-               for (@{$opt{exclude}}) {
-                       for my $ex (split /\s*,\s*/o => $_) {
-                               if ($ex =~ s/\.$//) {
-                                       if ($ex =~ s/^~//) {
-                                               ($stat += 2 and last) if $schema =~ /$ex/;
-                                       }
-                                       else {
-                                               ($stat += 2 and last) if $schema eq $ex;
-                                       }
-                               }
-                               elsif ($ex =~ s/^~//) {
-                                       ($stat += 2 and last) if $name =~ /$ex/;
-                               }
-                               else {
-                                       ($stat += 2 and last) if $name eq $ex;
-                               }
-                       }
-               }
-       }
-       if (defined $opt{include}) {
-               $stat += 4;
-               for (@{$opt{include}}) {
-                       for my $in (split /\s*,\s*/o => $_) {
-                               if ($in =~ s/\.$//) {
-                                       if ($in =~ s/^~//) {
-                                               ($stat += 8 and last) if $schema =~ /$in/;
-                                       }
-                                       else {
-                                               ($stat += 8 and last) if $schema eq $in;
-                                       }
-                               }
-                               elsif ($in =~ s/^~//) {
-                                       ($stat += 8 and last) if $name =~ /$in/;
-                               }
-                               else {
-                                       ($stat += 8 and last) if $name eq $in;
-                               }
-                       }
-               }
-       }
-
-       ## Easiest to state the cases when we DO skip:
-       return 1 if
-               3 == $stat     ## exclude matched, no inclusion checking
-               or 4 == $stat  ## include check only, no match
-               or 7 == $stat; ## exclude match, no inclusion match
-
-       return 0;
+    ## Determine if something should be skipped due to inclusion/exclusion options
+    ## Exclusion checked first: inclusion can pull it back in.
+    my $name = shift;
+    my $schema = shift || '';
+
+    my $stat = 0;
+    ## Is this excluded?
+    if (defined $opt{exclude}) {
+        $stat = 1;
+        for (@{$opt{exclude}}) {
+            for my $ex (split /\s*,\s*/o => $_) {
+                if ($ex =~ s/\.$//) {
+                    if ($ex =~ s/^~//) {
+                        ($stat += 2 and last) if $schema =~ /$ex/;
+                    }
+                    else {
+                        ($stat += 2 and last) if $schema eq $ex;
+                    }
+                }
+                elsif ($ex =~ s/^~//) {
+                    ($stat += 2 and last) if $name =~ /$ex/;
+                }
+                else {
+                    ($stat += 2 and last) if $name eq $ex;
+                }
+            }
+        }
+    }
+    if (defined $opt{include}) {
+        $stat += 4;
+        for (@{$opt{include}}) {
+            for my $in (split /\s*,\s*/o => $_) {
+                if ($in =~ s/\.$//) {
+                    if ($in =~ s/^~//) {
+                        ($stat += 8 and last) if $schema =~ /$in/;
+                    }
+                    else {
+                        ($stat += 8 and last) if $schema eq $in;
+                    }
+                }
+                elsif ($in =~ s/^~//) {
+                    ($stat += 8 and last) if $name =~ /$in/;
+                }
+                else {
+                    ($stat += 8 and last) if $name eq $in;
+                }
+            }
+        }
+    }
+
+    ## Easiest to state the cases when we DO skip:
+    return 1 if
+        3 == $stat     ## exclude matched, no inclusion checking
+        or 4 == $stat  ## include check only, no match
+        or 7 == $stat; ## exclude match, no inclusion match
+
+    return 0;
 
 } ## end of skip_item
 
 
 sub validate_range {
 
-       ## Valid that warning and critical are set correctly.
-       ## Returns new values of both
-
-       my $arg = shift;
-       defined $arg and ref $arg eq 'HASH' or ndie qq{validate_range must be called with a hashref\n};
-
-       return ('','') if $MRTG and !$arg->{forcemrtg};
-
-       my $type = $arg->{type} or ndie qq{validate_range must be provided a 'type'\n};
-
-       ## The 'default default' is an empty string, which should fail all mandatory tests
-       ## We only set the 'arg' default if neither option is provided.
-       my $warning  = exists $opt{warning}  ? $opt{warning} :
-               exists $opt{critical} ? '' : $arg->{default_warning} || '';
-       my $critical = exists $opt{critical} ? $opt{critical} :
-               exists $opt{warning} ? '' : $arg->{default_critical} || '';
-
-       if ('string' eq $type) {
-               ## Don't use this unless you have to
-       }
-       elsif ('seconds' eq $type) {
-               if (length $warning) {
-                       if ($warning !~ $timesecre) {
-                               ndie msg('range-seconds', 'warning');
-                       }
-                       $warning = $1;
-               }
-               if (length $critical) {
-                       if ($critical !~ $timesecre) {
-                               ndie msg('range-seconds', 'critical')
-                       }
-                       $critical = $1;
-                       if (length $warning and $warning > $critical) {
-                               ndie msg('range-warnbigtime', $warning, $critical);
-                       }
-               }
-       }
-       elsif ('time' eq $type) {
-               $critical = size_in_seconds($critical, 'critical');
-               $warning = size_in_seconds($warning, 'warning');
-               if (! length $critical and ! length $warning) {
-                       ndie msg('range-notime');
-               }
-               if (length $warning and length $critical and $warning > $critical) {
-                       ndie msg('range-warnbigtime', $warning, $critical);
-               }
-       }
-       elsif ('version' eq $type) {
-               my $msg = msg('range-version');
-               if (length $warning and $warning !~ /^\d+\.\d+\.?[\d\w]*$/) {
-                       ndie msg('range-badversion', 'warning', $msg);
-               }
-               if (length $critical and $critical !~ /^\d+\.\d+\.?[\d\w]*$/) {
-                       ndie msg('range-badversion', 'critical', $msg);
-               }
-               if (! length $critical and ! length $warning) {
-                       ndie msg('range-noopt-orboth');
-               }
-       }
-       elsif ('size' eq $type) {
-               if (length $critical) {
-                       if ($critical !~ $sizere) {
-                               ndie msg('range-badsize', 'critical');
-                       }
-                       $critical = size_in_bytes($1,$2);
-               }
-               if (length $warning) {
-                       if ($warning !~ $sizere) {
-                               ndie msg('range-badsize', 'warning');
-                       }
-                       $warning = size_in_bytes($1,$2);
-                       if (length $critical and $warning > $critical) {
-                               ndie msg('range-warnbigsize', $warning, $critical);
-                       }
-               }
-               elsif (!length $critical) {
-                       ndie msg('range-nosize');
-               }
-       }
-       elsif ($type =~ /integer/) {
-               $warning =~ s/_//g;
-               if (length $warning and $warning !~ /^\d+$/) {
-                       ndie $type =~ /positive/ ? msg('range-int-pos', 'warning') : msg('range-int', 'warning');
-               }
-               elsif (length $warning && $type =~ /positive/ && $warning <= 0) {
-                       ndie msg('range-int-pos', 'warning');
-               }
-
-               $critical =~ s/_//g;
-               if (length $critical and $critical !~ /^\d+$/) {
-                       ndie $type =~ /positive/ ? msg('range-int-pos', 'critical') : msg('range-int', 'critical');
-               }
-               elsif (length $critical && $type =~ /positive/ && $critical <= 0) {
-                       ndie msg('range-int-pos', 'critical');
-               }
-
-               if (length $warning
-                       and length $critical
-                       and (
-                               ($opt{reverse} and $warning < $critical)
-                               or
-                               (!$opt{reverse} and $warning > $critical)
-                               )
-                       ) {
-                       ndie msg('range-warnbig');
-               }
-       }
-       elsif ('restringex' eq $type) {
-               if (! length $critical and ! length $warning) {
-                       ndie msg('range-noopt-one');
-               }
-               if (length $critical and length $warning) {
-                       ndie msg('range-noopt-only');
-               }
-               my $string = length $critical ? $critical : $warning;
-               my $regex = ($string =~ s/^~//) ? '~' : '=';
-               $string =~ /^\w+$/ or ndie msg('invalid-option');
-       }
-       elsif ('percent' eq $type) {
-               if (length $critical) {
-                       if ($critical !~ /^\d+\%$/) {
-                               ndie msg('range-badpercent', 'critical');
-                       }
-               }
-               if (length $warning) {
-                       if ($warning !~ /^\d+\%$/) {
-                               ndie msg('range-badpercent', 'warning');
-                       }
-               }
-       }
-       elsif ('size or percent' eq $type) {
-               if (length $critical) {
-                       if ($critical =~ $sizere) {
-                               $critical = size_in_bytes($1,$2);
-                       }
-                       elsif ($critical !~ /^\d+\%$/) {
-                               ndie msg('range-badpercsize', 'critical');
-                       }
-               }
-               if (length $warning) {
-                       if ($warning =~ $sizere) {
-                               $warning = size_in_bytes($1,$2);
-                       }
-                       elsif ($warning !~ /^\d+\%$/) {
-                               ndie msg('range-badpercsize', 'warning');
-                       }
-               }
-               elsif (! length $critical) {
-                       ndie msg('range-noopt-size');
-               }
-       }
-       elsif ('checksum' eq $type) {
-               if (length $critical and $critical !~ $checksumre and $critical ne '0') {
-                       ndie msg('range-badcs', 'critical');
-               }
-               if (length $warning and $warning !~ $checksumre) {
-                       ndie msg('range-badcs', 'warning');
-               }
-       }
-       elsif ('multival' eq $type) { ## Simple number, or foo=#;bar=#
-               ## Note: only used for check_locks
-               my %err;
-               while ($critical =~ /(\w+)\s*=\s*(\d+)/gi) {
-                       my ($name,$val) = (lc $1,$2);
-                       $name =~ s/lock$//;
-                       $err{$name} = $val;
-               }
-               if (keys %err) {
-                       $critical = \%err;
-               }
-               elsif (length $critical and $critical =~ /^(\d+)$/) {
-                       $err{total} = $1;
-                       $critical = \%err;
-               }
-               elsif (length $critical) {
-                       ndie msg('range-badlock', 'critical');
-               }
-               my %warn;
-               while ($warning =~ /(\w+)\s*=\s*(\d+)/gi) {
-                       my ($name,$val) = (lc $1,$2);
-                       $name =~ s/lock$//;
-                       $warn{$name} = $val;
-               }
-               if (keys %warn) {
-                       $warning = \%warn;
-               }
-               elsif (length $warning and $warning =~ /^(\d+)$/) {
-                       $warn{total} = $1;
-                       $warning = \%warn;
-               }
-               elsif (length $warning) {
-                       ndie msg('range-badlock', 'warning');
-               }
-       }
-       elsif ('cacti' eq $type) { ## Takes no args, just dumps data
-               if (length $warning or length $critical) {
-                       ndie msg('range-cactionly');
-               }
-       }
-       else {
-               ndie msg('range-badtype', $type);
-       }
-
-       if ($arg->{both}) {
-               if (! length $warning or ! length $critical) {
-                       ndie msg('range-noopt-both');
-               }
-       }
-       if ($arg->{leastone}) {
-               if (! length $warning and ! length $critical) {
-                       ndie msg('range-noopt-one');
-               }
-       }
-       elsif ($arg->{onlyone}) {
-               if (length $warning and length $critical) {
-                       ndie msg('range-noopt-only');
-               }
-               if (! length $warning and ! length $critical) {
-                       ndie msg('range-noopt-one');
-               }
-       }
-
-       return ($warning,$critical);
+    ## Valid that warning and critical are set correctly.
+    ## Returns new values of both
+
+    my $arg = shift;
+    defined $arg and ref $arg eq 'HASH' or ndie qq{validate_range must be called with a hashref\n};
+
+    return ('','') if $MRTG and !$arg->{forcemrtg};
+
+    my $type = $arg->{type} or ndie qq{validate_range must be provided a 'type'\n};
+
+    ## The 'default default' is an empty string, which should fail all mandatory tests
+    ## We only set the 'arg' default if neither option is provided.
+    my $warning  = exists $opt{warning}  ? $opt{warning} :
+        exists $opt{critical} ? '' : $arg->{default_warning} || '';
+    my $critical = exists $opt{critical} ? $opt{critical} :
+        exists $opt{warning} ? '' : $arg->{default_critical} || '';
+
+    if ('string' eq $type) {
+        ## Don't use this unless you have to
+    }
+    elsif ('seconds' eq $type) {
+        if (length $warning) {
+            if ($warning !~ $timesecre) {
+                ndie msg('range-seconds', 'warning');
+            }
+            $warning = $1;
+        }
+        if (length $critical) {
+            if ($critical !~ $timesecre) {
+                ndie msg('range-seconds', 'critical')
+            }
+            $critical = $1;
+            if (length $warning and $warning > $critical) {
+                ndie msg('range-warnbigtime', $warning, $critical);
+            }
+        }
+    }
+    elsif ('time' eq $type) {
+        $critical = size_in_seconds($critical, 'critical');
+        $warning = size_in_seconds($warning, 'warning');
+        if (! length $critical and ! length $warning) {
+            ndie msg('range-notime');
+        }
+        if (length $warning and length $critical and $warning > $critical) {
+            ndie msg('range-warnbigtime', $warning, $critical);
+        }
+    }
+    elsif ('version' eq $type) {
+        my $msg = msg('range-version');
+        if (length $warning and $warning !~ /^\d+\.\d+\.?[\d\w]*$/) {
+            ndie msg('range-badversion', 'warning', $msg);
+        }
+        if (length $critical and $critical !~ /^\d+\.\d+\.?[\d\w]*$/) {
+            ndie msg('range-badversion', 'critical', $msg);
+        }
+        if (! length $critical and ! length $warning) {
+            ndie msg('range-noopt-orboth');
+        }
+    }
+    elsif ('size' eq $type) {
+        if (length $critical) {
+            if ($critical !~ $sizere) {
+                ndie msg('range-badsize', 'critical');
+            }
+            $critical = size_in_bytes($1,$2);
+        }
+        if (length $warning) {
+            if ($warning !~ $sizere) {
+                ndie msg('range-badsize', 'warning');
+            }
+            $warning = size_in_bytes($1,$2);
+            if (length $critical and $warning > $critical) {
+                ndie msg('range-warnbigsize', $warning, $critical);
+            }
+        }
+        elsif (!length $critical) {
+            ndie msg('range-nosize');
+        }
+    }
+    elsif ($type =~ /integer/) {
+        $warning =~ s/_//g;
+        if (length $warning and $warning !~ /^\d+$/) {
+            ndie $type =~ /positive/ ? msg('range-int-pos', 'warning') : msg('range-int', 'warning');
+        }
+        elsif (length $warning && $type =~ /positive/ && $warning <= 0) {
+            ndie msg('range-int-pos', 'warning');
+        }
+
+        $critical =~ s/_//g;
+        if (length $critical and $critical !~ /^\d+$/) {
+            ndie $type =~ /positive/ ? msg('range-int-pos', 'critical') : msg('range-int', 'critical');
+        }
+        elsif (length $critical && $type =~ /positive/ && $critical <= 0) {
+            ndie msg('range-int-pos', 'critical');
+        }
+
+        if (length $warning
+            and length $critical
+            and (
+                ($opt{reverse} and $warning < $critical)
+                or
+                (!$opt{reverse} and $warning > $critical)
+                )
+            ) {
+            ndie msg('range-warnbig');
+        }
+    }
+    elsif ('restringex' eq $type) {
+        if (! length $critical and ! length $warning) {
+            ndie msg('range-noopt-one');
+        }
+        if (length $critical and length $warning) {
+            ndie msg('range-noopt-only');
+        }
+        my $string = length $critical ? $critical : $warning;
+        my $regex = ($string =~ s/^~//) ? '~' : '=';
+        $string =~ /^\w+$/ or ndie msg('invalid-option');
+    }
+    elsif ('percent' eq $type) {
+        if (length $critical) {
+            if ($critical !~ /^\d+\%$/) {
+                ndie msg('range-badpercent', 'critical');
+            }
+        }
+        if (length $warning) {
+            if ($warning !~ /^\d+\%$/) {
+                ndie msg('range-badpercent', 'warning');
+            }
+        }
+    }
+    elsif ('size or percent' eq $type) {
+        if (length $critical) {
+            if ($critical =~ $sizere) {
+                $critical = size_in_bytes($1,$2);
+            }
+            elsif ($critical !~ /^\d+\%$/) {
+                ndie msg('range-badpercsize', 'critical');
+            }
+        }
+        if (length $warning) {
+            if ($warning =~ $sizere) {
+                $warning = size_in_bytes($1,$2);
+            }
+            elsif ($warning !~ /^\d+\%$/) {
+                ndie msg('range-badpercsize', 'warning');
+            }
+        }
+        elsif (! length $critical) {
+            ndie msg('range-noopt-size');
+        }
+    }
+    elsif ('checksum' eq $type) {
+        if (length $critical and $critical !~ $checksumre and $critical ne '0') {
+            ndie msg('range-badcs', 'critical');
+        }
+        if (length $warning and $warning !~ $checksumre) {
+            ndie msg('range-badcs', 'warning');
+        }
+    }
+    elsif ('multival' eq $type) { ## Simple number, or foo=#;bar=#
+        ## Note: only used for check_locks
+        my %err;
+        while ($critical =~ /(\w+)\s*=\s*(\d+)/gi) {
+            my ($name,$val) = (lc $1,$2);
+            $name =~ s/lock$//;
+            $err{$name} = $val;
+        }
+        if (keys %err) {
+            $critical = \%err;
+        }
+        elsif (length $critical and $critical =~ /^(\d+)$/) {
+            $err{total} = $1;
+            $critical = \%err;
+        }
+        elsif (length $critical) {
+            ndie msg('range-badlock', 'critical');
+        }
+        my %warn;
+        while ($warning =~ /(\w+)\s*=\s*(\d+)/gi) {
+            my ($name,$val) = (lc $1,$2);
+            $name =~ s/lock$//;
+            $warn{$name} = $val;
+        }
+        if (keys %warn) {
+            $warning = \%warn;
+        }
+        elsif (length $warning and $warning =~ /^(\d+)$/) {
+            $warn{total} = $1;
+            $warning = \%warn;
+        }
+        elsif (length $warning) {
+            ndie msg('range-badlock', 'warning');
+        }
+    }
+    elsif ('cacti' eq $type) { ## Takes no args, just dumps data
+        if (length $warning or length $critical) {
+            ndie msg('range-cactionly');
+        }
+    }
+    else {
+        ndie msg('range-badtype', $type);
+    }
+
+    if ($arg->{both}) {
+        if (! length $warning or ! length $critical) {
+            ndie msg('range-noopt-both');
+        }
+    }
+    if ($arg->{leastone}) {
+        if (! length $warning and ! length $critical) {
+            ndie msg('range-noopt-one');
+        }
+    }
+    elsif ($arg->{onlyone}) {
+        if (length $warning and length $critical) {
+            ndie msg('range-noopt-only');
+        }
+        if (! length $warning and ! length $critical) {
+            ndie msg('range-noopt-one');
+        }
+    }
+
+    return ($warning,$critical);
 
 } ## end of validate_range
 
 
 sub check_autovac_freeze {
 
-       ## Check how close all databases are to autovacuum_freeze_max_age
-       ## Supports: Nagios, MRTG
-       ## It makes no sense to run this more than once on the same cluster
-       ## Warning and criticals are percentages
-       ## Can also ignore databases with exclude, and limit with include
+    ## Check how close all databases are to autovacuum_freeze_max_age
+    ## Supports: Nagios, MRTG
+    ## It makes no sense to run this more than once on the same cluster
+    ## Warning and criticals are percentages
+    ## Can also ignore databases with exclude, and limit with include
 
-       my ($warning, $critical) = validate_range
-               ({
-                 type              => 'percent',
-                 default_warning   => '90%',
-                 default_critical  => '95%',
-                 forcemrtg         => 1,
-                 });
+    my ($warning, $critical) = validate_range
+        ({
+          type              => 'percent',
+          default_warning   => '90%',
+          default_critical  => '95%',
+          forcemrtg         => 1,
+          });
 
-       (my $w = $warning) =~ s/\D//;
-       (my $c = $critical) =~ s/\D//;
+    (my $w = $warning) =~ s/\D//;
+    (my $c = $critical) =~ s/\D//;
 
-       my $SQL = q{SELECT freez, txns, ROUND(100*(txns/freez::float)) AS perc, datname}.
-               q{ FROM (SELECT foo.freez::int, age(datfrozenxid) AS txns, datname}.
-               q{ FROM pg_database d JOIN (SELECT setting AS freez FROM pg_settings WHERE name = 'autovacuum_freeze_max_age') AS foo}.
-               q{ ON (true) WHERE d.datallowconn) AS foo2 ORDER BY 3 DESC, 4 ASC};
+    my $SQL = q{SELECT freez, txns, ROUND(100*(txns/freez::float)) AS perc, datname}.
+        q{ FROM (SELECT foo.freez::int, age(datfrozenxid) AS txns, datname}.
+        q{ FROM pg_database d JOIN (SELECT setting AS freez FROM pg_settings WHERE name = 'autovacuum_freeze_max_age') AS foo}.
+        q{ ON (true) WHERE d.datallowconn) AS foo2 ORDER BY 3 DESC, 4 ASC};
 
-       my $info = run_command($SQL, {regex => qr{\w+} } );
+    my $info = run_command($SQL, {regex => qr{\w+} } );
 
-       $db = $info->{db}[0];
+    $db = $info->{db}[0];
 
-       my (@crit,@warn,@ok);
-       my ($maxp,$maxt,$maxdb) = (0,0,''); ## used by MRTG only
+    my (@crit,@warn,@ok);
+    my ($maxp,$maxt,$maxdb) = (0,0,''); ## used by MRTG only
   SLURP: for my $r (@{$db->{slurp}}) {
-               next SLURP if skip_item($r->{datname});
-
-               if ($MRTG) {
-                       if ($r->{perc} > $maxp) {
-                               $maxdb = $r->{datname};
-                               $maxp = $r->{perc};
-                       }
-                       elsif ($r->{perc} == $maxp) {
-                               $maxdb .= sprintf '%s%s', (length $maxdb ? ' | ' : ''), $r->{datname};
-                       }
-                       $maxt = $r->{tnxs} if $r->{txns} > $maxt;
-                       next SLURP;
-               }
-
-               my $msg = "'$r->{datname}'=$r->{perc}\%;$w;$c";
-               $db->{perf} .= " $msg";
-               if (length $critical and $r->{perc} >= $c) {
-                       push @crit => $msg;
-               }
-               elsif (length $warning and $r->{perc} >= $w) {
-                       push @warn => $msg;
-               }
-               else {
-                       push @ok => $msg;
-               }
-       }
-       if ($MRTG) {
-               do_mrtg({one => $maxp, two => $maxt, msg => $maxdb});
-       }
-       if (@crit) {
-               add_critical join ' ' => @crit;
-       }
-       elsif (@warn) {
-               add_warning join ' ' => @warn;
-       }
-       else {
-               add_ok join ' ' => @ok;
-       }
-
-       return;
+        next SLURP if skip_item($r->{datname});
+
+        if ($MRTG) {
+            if ($r->{perc} > $maxp) {
+                $maxdb = $r->{datname};
+                $maxp = $r->{perc};
+            }
+            elsif ($r->{perc} == $maxp) {
+                $maxdb .= sprintf '%s%s', (length $maxdb ? ' | ' : ''), $r->{datname};
+            }
+            $maxt = $r->{tnxs} if $r->{txns} > $maxt;
+            next SLURP;
+        }
+
+        my $msg = "'$r->{datname}'=$r->{perc}\%;$w;$c";
+        $db->{perf} .= " $msg";
+        if (length $critical and $r->{perc} >= $c) {
+            push @crit => $msg;
+        }
+        elsif (length $warning and $r->{perc} >= $w) {
+            push @warn => $msg;
+        }
+        else {
+            push @ok => $msg;
+        }
+    }
+    if ($MRTG) {
+        do_mrtg({one => $maxp, two => $maxt, msg => $maxdb});
+    }
+    if (@crit) {
+        add_critical join ' ' => @crit;
+    }
+    elsif (@warn) {
+        add_warning join ' ' => @warn;
+    }
+    else {
+        add_ok join ' ' => @ok;
+    }
+
+    return;
 
 } ## end of check_autovac_freeze
 
 
 sub check_backends {
 
-       ## Check the number of connections
-       ## Supports: Nagios, MRTG
-       ## It makes no sense to run this more than once on the same cluster
-       ## Need to be superuser, else only your queries will be visible
-       ## Warning and criticals can take three forms:
-       ## critical = 12 -- complain if there are 12 or more connections
-       ## critical = 95% -- complain if >= 95% of available connections are used
-       ## critical = -5 -- complain if there are only 5 or fewer connection slots left
-       ## The former two options only work with simple numbers - no percentage or negative
-       ## Can also ignore databases with exclude, and limit with include
-
-       my $warning  = $opt{warning}  || '90%';
-       my $critical = $opt{critical} || '95%';
-       my $noidle   = $opt{noidle}   || 0;
-
-       ## If only critical was used, remove the default warning
-       if ($opt{critical} and !$opt{warning}) {
-               $warning = $critical;
-       }
-
-       my $validre = qr{^(\-?)(\d+)(\%?)$};
-       if ($critical !~ $validre) {
-               ndie msg('backends-users', 'Critical');
-       }
-       my ($e1,$e2,$e3) = ($1,$2,$3);
-       if ($warning !~ $validre) {
-               ndie msg('backends-users', 'Warning');
-       }
-       my ($w1,$w2,$w3) = ($1,$2,$3);
-
-       ## If number is greater, all else is same, and not minus
-       if ($w2 > $e2 and $w1 eq $e1 and $w3 eq $e3 and $w1 eq '') {
-               ndie msg('range-warnbig');
-       }
-       ## If number is less, all else is same, and minus
-       if ($w2 < $e2 and $w1 eq $e1 and $w3 eq $e3 and $w1 eq '-') {
-               ndie msg('range-warnsmall');
-       }
-       if (($w1 and $w3) or ($e1 and $e3)) {
-               ndie msg('range-neg-percent');
-       }
-
-       my $MAXSQL = q{SELECT setting AS mc FROM pg_settings WHERE name = 'max_connections'};
-
-       my $NOIDLE = $noidle ? q{WHERE current_query <> '<IDLE>'} : '';
-       $SQL = qq{
+    ## Check the number of connections
+    ## Supports: Nagios, MRTG
+    ## It makes no sense to run this more than once on the same cluster
+    ## Need to be superuser, else only your queries will be visible
+    ## Warning and criticals can take three forms:
+    ## critical = 12 -- complain if there are 12 or more connections
+    ## critical = 95% -- complain if >= 95% of available connections are used
+    ## critical = -5 -- complain if there are only 5 or fewer connection slots left
+    ## The former two options only work with simple numbers - no percentage or negative
+    ## Can also ignore databases with exclude, and limit with include
+
+    my $warning  = $opt{warning}  || '90%';
+    my $critical = $opt{critical} || '95%';
+    my $noidle   = $opt{noidle}   || 0;
+
+    ## If only critical was used, remove the default warning
+    if ($opt{critical} and !$opt{warning}) {
+        $warning = $critical;
+    }
+
+    my $validre = qr{^(\-?)(\d+)(\%?)$};
+    if ($critical !~ $validre) {
+        ndie msg('backends-users', 'Critical');
+    }
+    my ($e1,$e2,$e3) = ($1,$2,$3);
+    if ($warning !~ $validre) {
+        ndie msg('backends-users', 'Warning');
+    }
+    my ($w1,$w2,$w3) = ($1,$2,$3);
+
+    ## If number is greater, all else is same, and not minus
+    if ($w2 > $e2 and $w1 eq $e1 and $w3 eq $e3 and $w1 eq '') {
+        ndie msg('range-warnbig');
+    }
+    ## If number is less, all else is same, and minus
+    if ($w2 < $e2 and $w1 eq $e1 and $w3 eq $e3 and $w1 eq '-') {
+        ndie msg('range-warnsmall');
+    }
+    if (($w1 and $w3) or ($e1 and $e3)) {
+        ndie msg('range-neg-percent');
+    }
+
+    my $MAXSQL = q{SELECT setting AS mc FROM pg_settings WHERE name = 'max_connections'};
+
+    my $NOIDLE = $noidle ? q{WHERE current_query <> '<IDLE>'} : '';
+    $SQL = qq{
 SELECT COUNT(datid) AS current,
   ($MAXSQL) AS mc,
   d.datname
@@ -2550,165 +2550,165 @@ LEFT JOIN pg_stat_activity s ON (s.datid = d.oid) $NOIDLE
 GROUP BY 2,3
 ORDER BY datname
 };
-       my $info = run_command($SQL, {regex => qr{\d+}, fatalregex => 'too many clients' } );
-
-       $db = $info->{db}[0];
-
-       ## If we cannot connect because of too many clients, we treat as a critical error
-       if (exists $info->{fatalregex}) {
-               my $regmsg = msg('backends-po');
-               my $regmsg2 = msg_en('backends-po');
-               if ($info->{fatalregex} =~ /$regmsg/ or $info->{fatalregex} =~ /$regmsg2/) {
-                       add_critical msg('backends-fatal');
-                       return;
-               }
-       }
-
-       ## There may be no entries returned if we catch pg_stat_activity at the right
-       ## moment in older versions of Postgres
-       if (! defined $db) {
-               $info = run_command($MAXSQL, {regex => qr[\d] } );
-               $db = $info->{db}[0];
-               if (!defined $db->{slurp} or $db->{slurp} !~ /(\d+)/) {
-                       undef %unknown;
-                       add_unknown msg('backends-nomax');
-                       return;
-               }
-               my $limit = $1;
-               if ($MRTG) {
-                       do_mrtg({one => 1, msg => msg('backends-mrtg', $db->{dbname}, $limit)});
-               }
-               my $percent = (int 1/$limit*100) || 1;
-               add_ok msg('backends-msg', 1, $limit, $percent);
-               return;
-       }
-
-       my $total = 0;
-       my $grandtotal = @{$db->{slurp}};
-
-       ## If no max_connections, something is wrong
-       if ($db->{slurp}[0]{mc} !~ /\d/) {
-               add_unknown msg('backends-nomax');
-               return;
-       }
-       my $limit = $db->{slurp}[0]{mc};
-
-       for my $r (@{$db->{slurp}}) {
-
-               ## Always want perf to show all
-               my $nwarn=$w2;
-               my $ncrit=$e2;
-               if ($e1) {
-                       $ncrit = $limit-$e2;
-               }
-               elsif ($e3) {
-                       $ncrit = (int $e2*$limit/100);
-               }
-               if ($w1) {
-                       $nwarn = $limit-$w2;
-               }
-               elsif ($w3) {
-                       $nwarn = (int $w2*$limit/100)
-               }
-               $db->{perf} .= " '$r->{datname}'=$r->{current};$nwarn;$ncrit;0;$limit";
-
-               if (! skip_item($r->{datname})) {
-                       $total += $r->{current};
-               }
-       }
-
-       if ($MRTG) {
-               $stats{$db->{dbname}} = $total;
-               $statsmsg{$db->{dbname}} = msg('backends-mrtg', $db->{dbname}, $limit);
-               return;
-       }
-
-       if (!$total) {
-               if ($grandtotal) {
-                       ## We assume that exclude/include rules are correct, and we simply had no entries
-                       ## at all in the specific databases we wanted
-                       add_ok msg('backends-oknone');
-               }
-               else {
-                       add_unknown msg('no-match-db');
-               }
-               return;
-       }
-
-       my $percent = (int $total / $limit*100) || 1;
-       my $msg = msg('backends-msg', $total, $limit, $percent);
-       my $ok = 1;
-       if ($e1) { ## minus
-               $ok = 0 if $limit-$total >= $e2;
-       }
-       elsif ($e3) { ## percent
-               my $nowpercent = $total/$limit*100;
-               $ok = 0 if $nowpercent >= $e2;
-       }
-       else { ## raw number
-               $ok = 0 if $total >= $e2;
-       }
-       if (!$ok) {
-               add_critical $msg;
-               return;
-       }
-
-       if ($w1) {
-               $ok = 0 if $limit-$total >= $w2;
-       }
-       elsif ($w3) {
-               my $nowpercent = $total/$limit*100;
-               $ok = 0 if $nowpercent >= $w2;
-       }
-       else {
-               $ok = 0 if $total >= $w2;
-       }
-       if (!$ok) {
-               add_warning $msg;
-               return;
-       }
-
-       add_ok $msg;
-
-       return;
+    my $info = run_command($SQL, {regex => qr{\d+}, fatalregex => 'too many clients' } );
+
+    $db = $info->{db}[0];
+
+    ## If we cannot connect because of too many clients, we treat as a critical error
+    if (exists $info->{fatalregex}) {
+        my $regmsg = msg('backends-po');
+        my $regmsg2 = msg_en('backends-po');
+        if ($info->{fatalregex} =~ /$regmsg/ or $info->{fatalregex} =~ /$regmsg2/) {
+            add_critical msg('backends-fatal');
+            return;
+        }
+    }
+
+    ## There may be no entries returned if we catch pg_stat_activity at the right
+    ## moment in older versions of Postgres
+    if (! defined $db) {
+        $info = run_command($MAXSQL, {regex => qr[\d] } );
+        $db = $info->{db}[0];
+        if (!defined $db->{slurp} or $db->{slurp} !~ /(\d+)/) {
+            undef %unknown;
+            add_unknown msg('backends-nomax');
+            return;
+        }
+        my $limit = $1;
+        if ($MRTG) {
+            do_mrtg({one => 1, msg => msg('backends-mrtg', $db->{dbname}, $limit)});
+        }
+        my $percent = (int 1/$limit*100) || 1;
+        add_ok msg('backends-msg', 1, $limit, $percent);
+        return;
+    }
+
+    my $total = 0;
+    my $grandtotal = @{$db->{slurp}};
+
+    ## If no max_connections, something is wrong
+    if ($db->{slurp}[0]{mc} !~ /\d/) {
+        add_unknown msg('backends-nomax');
+        return;
+    }
+    my $limit = $db->{slurp}[0]{mc};
+
+    for my $r (@{$db->{slurp}}) {
+
+        ## Always want perf to show all
+        my $nwarn=$w2;
+        my $ncrit=$e2;
+        if ($e1) {
+            $ncrit = $limit-$e2;
+        }
+        elsif ($e3) {
+            $ncrit = (int $e2*$limit/100);
+        }
+        if ($w1) {
+            $nwarn = $limit-$w2;
+        }
+        elsif ($w3) {
+            $nwarn = (int $w2*$limit/100)
+        }
+        $db->{perf} .= " '$r->{datname}'=$r->{current};$nwarn;$ncrit;0;$limit";
+
+        if (! skip_item($r->{datname})) {
+            $total += $r->{current};
+        }
+    }
+
+    if ($MRTG) {
+        $stats{$db->{dbname}} = $total;
+        $statsmsg{$db->{dbname}} = msg('backends-mrtg', $db->{dbname}, $limit);
+        return;
+    }
+
+    if (!$total) {
+        if ($grandtotal) {
+            ## We assume that exclude/include rules are correct, and we simply had no entries
+            ## at all in the specific databases we wanted
+            add_ok msg('backends-oknone');
+        }
+        else {
+            add_unknown msg('no-match-db');
+        }
+        return;
+    }
+
+    my $percent = (int $total / $limit*100) || 1;
+    my $msg = msg('backends-msg', $total, $limit, $percent);
+    my $ok = 1;
+    if ($e1) { ## minus
+        $ok = 0 if $limit-$total >= $e2;
+    }
+    elsif ($e3) { ## percent
+        my $nowpercent = $total/$limit*100;
+        $ok = 0 if $nowpercent >= $e2;
+    }
+    else { ## raw number
+        $ok = 0 if $total >= $e2;
+    }
+    if (!$ok) {
+        add_critical $msg;
+        return;
+    }
+
+    if ($w1) {
+        $ok = 0 if $limit-$total >= $w2;
+    }
+    elsif ($w3) {
+        my $nowpercent = $total/$limit*100;
+        $ok = 0 if $nowpercent >= $w2;
+    }
+    else {
+        $ok = 0 if $total >= $w2;
+    }
+    if (!$ok) {
+        add_warning $msg;
+        return;
+    }
+
+    add_ok $msg;
+
+    return;
 
 } ## end of check_backends
 
 
 sub check_bloat {
 
-       ## Check how bloated the tables and indexes are
-       ## Supports: Nagios, MRTG
-       ## NOTE! This check depends on ANALYZE being run regularly
-       ## Also requires stats collection to be on
-       ## This action may be very slow on large databases
-       ## By default, checks all relations
-       ## Can check specific one(s) with include; can ignore some with exclude
-       ## Begin name with a '~' to make it a regular expression
-       ## Warning and critical are in sizes, defaults to bytes
-       ## Valid units: b, k, m, g, t, e
-       ## All above may be written as plural or with a trailing 'b'
-       ## Example: --critical="25 GB" --include="mylargetable"
-       ## Can also specify percentages
-
-       ## Don't bother with tables or indexes unless they have at least this many bloated pages
-       my $MINPAGES = 0;
-       my $MINIPAGES = 10;
-
-       my $LIMIT = 10;
-       if ($opt{perflimit}) {
-               $LIMIT = $opt{perflimit};
-       }
-
-       my ($warning, $critical) = validate_range
-               ({
-                 type               => 'size or percent',
-                 default_warning    => '1 GB',
-                 default_critical   => '5 GB',
-                 });
-
-       ## This was fun to write
-       $SQL = q{
+    ## Check how bloated the tables and indexes are
+    ## Supports: Nagios, MRTG
+    ## NOTE! This check depends on ANALYZE being run regularly
+    ## Also requires stats collection to be on
+    ## This action may be very slow on large databases
+    ## By default, checks all relations
+    ## Can check specific one(s) with include; can ignore some with exclude
+    ## Begin name with a '~' to make it a regular expression
+    ## Warning and critical are in sizes, defaults to bytes
+    ## Valid units: b, k, m, g, t, e
+    ## All above may be written as plural or with a trailing 'b'
+    ## Example: --critical="25 GB" --include="mylargetable"
+    ## Can also specify percentages
+
+    ## Don't bother with tables or indexes unless they have at least this many bloated pages
+    my $MINPAGES = 0;
+    my $MINIPAGES = 10;
+
+    my $LIMIT = 10;
+    if ($opt{perflimit}) {
+        $LIMIT = $opt{perflimit};
+    }
+
+    my ($warning, $critical) = validate_range
+        ({
+          type               => 'size or percent',
+          default_warning    => '1 GB',
+          default_critical   => '5 GB',
+          });
+
+    ## This was fun to write
+    $SQL = q{
 SELECT
   current_database() AS db, schemaname, tablename, reltuples::bigint AS tups, relpages::bigint AS pages, otta,
   ROUND(CASE WHEN otta=0 THEN 0.0 ELSE sml.relpages/otta::numeric END,1) AS tbloat,
@@ -2759,385 +2759,385 @@ FROM (
 ) AS sml
 };
 
-       if (! defined $opt{include} and ! defined $opt{exclude}) {
-               $SQL .= " WHERE sml.relpages - otta > $MINPAGES OR ipages - iotta > $MINIPAGES";
-               $SQL .= " ORDER BY wastedbytes DESC LIMIT $LIMIT";
-       }
-       else {
-               $SQL .= ' ORDER BY wastedbytes DESC';
-       }
-
-       if ($psql_version <= 7.4) {
-               $SQL =~ s/BLOCK_SIZE/(SELECT 8192) AS bs/;
-       }
-       else {
-               $SQL =~ s/BLOCK_SIZE/(SELECT current_setting('block_size')::numeric) AS bs/;
-       }
-
-       my $info = run_command($SQL);
-
-       if (defined $info->{db}[0] and exists $info->{db}[0]{error}) {
-               ndie $info->{db}[0]{error};
-       }
-
-       my %seenit;
-       for $db (@{$info->{db}}) {
-               if ($db->{slurp}[0] !~ /\w+/o) {
-                       add_ok msg('bloat-nomin') unless $MRTG;
-                       return;
-               }
-               ## Not a 'regex' to run_command as we need to check the above first.
-               if ($db->{slurp}[0] !~ /\d+/) {
-                       add_unknown msg('invalid-query', $db->{slurp}) unless $MRTG;
-                       return;
-               }
-
-               my $max = -1;
-               my $maxmsg = '?';
-
-               for my $r (@{$db->{slurp}}) {
-
-                       my ($dbname,$schema,$table,$tups,$pages,$otta,$bloat,$wp,$wb,$ws) = @$r{
-                               qw/ db schemaname tablename tups pages otta tbloat wastedpages wastedbytes wastedsize/};
-                       my ($index,$irows,$ipages,$iotta,$ibloat,$iwp,$iwb,$iws) = @$r{
-                                       qw/ iname irows ipages iotta ibloat wastedipgaes wastedibytes wastedisize/};
-
-                       next if skip_item($table, $schema);
-
-                       ## Made it past the exclusions
-                       $max = -2 if $max == -1;
-
-                       for my $v (values %$r) {
-                               $v =~ s/\| (\d+) bytes/'| ' . pretty_size($1,1)/ge;
-                       }
-
-                       ## Do the table first if we haven't seen it
-                       if (! $seenit{"$dbname.$schema.$table"}++) {
-                               $db->{perf} .= " $schema.$table=$wb";
-                               my $msg = msg('bloat-table', $dbname, $schema, $table, $tups, $pages, $otta, $bloat, $wb, $ws);
-                               my $ok = 1;
-                               my $perbloat = $bloat * 100;
-
-                               if ($MRTG) {
-                                       $stats{table}{"DB=$dbname TABLE=$schema.$table"} = [$wb, $bloat];
-                                       next;
-                               }
-                               if (length $critical) {
-                                       if (index($critical,'%')>=0) {
-                                               (my $critical2 = $critical) =~ s/\%//;
-                                               if ($perbloat >= $critical2) {
-                                                       add_critical $msg;
-                                                       $ok = 0;
-                                               }
-                                       }
-                                       elsif ($wb >= $critical) {
-                                               add_critical $msg;
-                                               $ok = 0;
-                                       }
-                               }
-
-                               if (length $warning and $ok) {
-                                       if (index($warning,'%')>=0) {
-                                               (my $warning2 = $warning) =~ s/\%//;
-                                               if ($perbloat >= $warning2) {
-                                                       add_warning $msg;
-                                                       $ok = 0;
-                                               }
-                                       }
-                                       elsif ($wb >= $warning) {
-                                               add_warning $msg;
-                                               $ok = 0;
-                                       }
-                               }
-                               ($max = $wb, $maxmsg = $msg) if $wb > $max and $ok;
-                       }
-
-                       ## Now the index, if it exists
-                       if ($index ne '?') {
-                               $db->{perf} .= " $index=$iwb" if $iwb;
-                               my $msg = msg('bloat-index', $dbname, $index, $irows, $ipages, $iotta, $ibloat, $iwb, $iws);
-                               my $ok = 1;
-                               my $iperbloat = $ibloat * 100;
-
-                               if ($MRTG) {
-                                       $stats{index}{"DB=$dbname INDEX=$index"} = [$iwb, $ibloat];
-                                       next;
-                               }
-                               if (length $critical) {
-                                       if (index($critical,'%')>=0) {
-                                               (my $critical2 = $critical) =~ s/\%//;
-                                               if ($iperbloat >= $critical2) {
-                                                       add_critical $msg;
-                                                       $ok = 0;
-                                               }
-                                       }
-                                       elsif ($iwb >= $critical) {
-                                               add_critical $msg;
-                                               $ok = 0;
-                                       }
-                               }
-
-                               if (length $warning and $ok) {
-                                       if (index($warning,'%')>=0) {
-                                               (my $warning2 = $warning) =~ s/\%//;
-                                               if ($iperbloat >= $warning2) {
-                                                       add_warning $msg;
-                                                       $ok = 0;
-                                               }
-                                       }
-                                       elsif ($iwb >= $warning) {
-                                               add_warning $msg;
-                                               $ok = 0;
-                                       }
-                               }
-
-                               ($max = $iwb, $maxmsg = $msg) if $iwb > $max and $ok;
-                       }
-               }
-               if ($max == -1) {
-                       add_unknown msg('no-match-rel');
-               }
-               elsif ($max != -1) {
-                       add_ok $maxmsg;
-               }
-       }
-
-       if ($MRTG) {
-               keys %stats or bad_mrtg(msg('unknown-error'));
-               ## We are going to report the highest wasted bytes for table and index
-               my ($one,$two,$msg) = ('','');
-               ## Can also sort by ratio
-               my $sortby = exists $opt{mrtg} and $opt{mrtg} eq 'ratio' ? 1 : 0;
-               for (sort { $stats{table}{$b}->[$sortby] <=> $stats{table}{$a}->[$sortby] } keys %{$stats{table}}) {
-                       $one = $stats{table}{$_}->[$sortby];
-                       $msg = $_;
-                       last;
-               }
-               for (sort { $stats{index}{$b}->[$sortby] <=> $stats{index}{$a}->[$sortby] } keys %{$stats{index}}) {
-                       $two = $stats{index}{$_}->[$sortby];
-                       $msg .= " $_";
-                       last;
-               }
-               do_mrtg({one => $one, two => $two, msg => $msg});
-       }
-
-       return;
+    if (! defined $opt{include} and ! defined $opt{exclude}) {
+        $SQL .= " WHERE sml.relpages - otta > $MINPAGES OR ipages - iotta > $MINIPAGES";
+        $SQL .= " ORDER BY wastedbytes DESC LIMIT $LIMIT";
+    }
+    else {
+        $SQL .= ' ORDER BY wastedbytes DESC';
+    }
+
+    if ($psql_version <= 7.4) {
+        $SQL =~ s/BLOCK_SIZE/(SELECT 8192) AS bs/;
+    }
+    else {
+        $SQL =~ s/BLOCK_SIZE/(SELECT current_setting('block_size')::numeric) AS bs/;
+    }
+
+    my $info = run_command($SQL);
+
+    if (defined $info->{db}[0] and exists $info->{db}[0]{error}) {
+        ndie $info->{db}[0]{error};
+    }
+
+    my %seenit;
+    for $db (@{$info->{db}}) {
+        if ($db->{slurp}[0] !~ /\w+/o) {
+            add_ok msg('bloat-nomin') unless $MRTG;
+            return;
+        }
+        ## Not a 'regex' to run_command as we need to check the above first.
+        if ($db->{slurp}[0] !~ /\d+/) {
+            add_unknown msg('invalid-query', $db->{slurp}) unless $MRTG;
+            return;
+        }
+
+        my $max = -1;
+        my $maxmsg = '?';
+
+        for my $r (@{$db->{slurp}}) {
+
+            my ($dbname,$schema,$table,$tups,$pages,$otta,$bloat,$wp,$wb,$ws) = @$r{
+                qw/ db schemaname tablename tups pages otta tbloat wastedpages wastedbytes wastedsize/};
+            my ($index,$irows,$ipages,$iotta,$ibloat,$iwp,$iwb,$iws) = @$r{
+                    qw/ iname irows ipages iotta ibloat wastedipgaes wastedibytes wastedisize/};
+
+            next if skip_item($table, $schema);
+
+            ## Made it past the exclusions
+            $max = -2 if $max == -1;
+
+            for my $v (values %$r) {
+                $v =~ s/\| (\d+) bytes/'| ' . pretty_size($1,1)/ge;
+            }
+
+            ## Do the table first if we haven't seen it
+            if (! $seenit{"$dbname.$schema.$table"}++) {
+                $db->{perf} .= " $schema.$table=$wb";
+                my $msg = msg('bloat-table', $dbname, $schema, $table, $tups, $pages, $otta, $bloat, $wb, $ws);
+                my $ok = 1;
+                my $perbloat = $bloat * 100;
+
+                if ($MRTG) {
+                    $stats{table}{"DB=$dbname TABLE=$schema.$table"} = [$wb, $bloat];
+                    next;
+                }
+                if (length $critical) {
+                    if (index($critical,'%')>=0) {
+                        (my $critical2 = $critical) =~ s/\%//;
+                        if ($perbloat >= $critical2) {
+                            add_critical $msg;
+                            $ok = 0;
+                        }
+                    }
+                    elsif ($wb >= $critical) {
+                        add_critical $msg;
+                        $ok = 0;
+                    }
+                }
+
+                if (length $warning and $ok) {
+                    if (index($warning,'%')>=0) {
+                        (my $warning2 = $warning) =~ s/\%//;
+                        if ($perbloat >= $warning2) {
+                            add_warning $msg;
+                            $ok = 0;
+                        }
+                    }
+                    elsif ($wb >= $warning) {
+                        add_warning $msg;
+                        $ok = 0;
+                    }
+                }
+                ($max = $wb, $maxmsg = $msg) if $wb > $max and $ok;
+            }
+
+            ## Now the index, if it exists
+            if ($index ne '?') {
+                $db->{perf} .= " $index=$iwb" if $iwb;
+                my $msg = msg('bloat-index', $dbname, $index, $irows, $ipages, $iotta, $ibloat, $iwb, $iws);
+                my $ok = 1;
+                my $iperbloat = $ibloat * 100;
+
+                if ($MRTG) {
+                    $stats{index}{"DB=$dbname INDEX=$index"} = [$iwb, $ibloat];
+                    next;
+                }
+                if (length $critical) {
+                    if (index($critical,'%')>=0) {
+                        (my $critical2 = $critical) =~ s/\%//;
+                        if ($iperbloat >= $critical2) {
+                            add_critical $msg;
+                            $ok = 0;
+                        }
+                    }
+                    elsif ($iwb >= $critical) {
+                        add_critical $msg;
+                        $ok = 0;
+                    }
+                }
+
+                if (length $warning and $ok) {
+                    if (index($warning,'%')>=0) {
+                        (my $warning2 = $warning) =~ s/\%//;
+                        if ($iperbloat >= $warning2) {
+                            add_warning $msg;
+                            $ok = 0;
+                        }
+                    }
+                    elsif ($iwb >= $warning) {
+                        add_warning $msg;
+                        $ok = 0;
+                    }
+                }
+
+                ($max = $iwb, $maxmsg = $msg) if $iwb > $max and $ok;
+            }
+        }
+        if ($max == -1) {
+            add_unknown msg('no-match-rel');
+        }
+        elsif ($max != -1) {
+            add_ok $maxmsg;
+        }
+    }
+
+    if ($MRTG) {
+        keys %stats or bad_mrtg(msg('unknown-error'));
+        ## We are going to report the highest wasted bytes for table and index
+        my ($one,$two,$msg) = ('','');
+        ## Can also sort by ratio
+        my $sortby = exists $opt{mrtg} and $opt{mrtg} eq 'ratio' ? 1 : 0;
+        for (sort { $stats{table}{$b}->[$sortby] <=> $stats{table}{$a}->[$sortby] } keys %{$stats{table}}) {
+            $one = $stats{table}{$_}->[$sortby];
+            $msg = $_;
+            last;
+        }
+        for (sort { $stats{index}{$b}->[$sortby] <=> $stats{index}{$a}->[$sortby] } keys %{$stats{index}}) {
+            $two = $stats{index}{$_}->[$sortby];
+            $msg .= " $_";
+            last;
+        }
+        do_mrtg({one => $one, two => $two, msg => $msg});
+    }
+
+    return;
 
 } ## end of check_bloat
 
 
 sub check_checkpoint {
 
-       ## Checks how long in seconds since the last checkpoint on a WAL slave
-       ## Supports: Nagios, MRTG
-       ## Warning and critical are seconds
-       ## Requires $ENV{PGDATA} or --datadir
-
-       my ($warning, $critical) = validate_range
-               ({
-                 type              => 'time',
-                 leastone          => 1,
-                 forcemrtg         => 1,
-       });
-
-       ## Find the data directory, make sure it exists
-       my $dir = $opt{datadir} || $ENV{PGDATA};
-
-       if (!defined $dir or ! length $dir) {
-               ndie msg('checkpoint-nodir');
-       }
-
-       if (! -d $dir) {
-               ndie msg('checkpoint-baddir', $dir);
-       }
-
-       $db->{host} = '<none>';
-
-       ## Run pg_controldata, grab the time
-       my $pgc
-               = $ENV{PGCONTROLDATA} ? $ENV{PGCONTROLDATA}
-               : $ENV{PGBINDIR}      ? "$ENV{PGBINDIR}/pg_controldata"
-               :                       'pg_controldata';
-       $COM = qq{$pgc "$dir"};
-       eval {
-               $res = qx{$COM 2>&1};
-       };
-       if ($@) {
-               ndie msg('checkpoint-nosys', $@);
-       }
-
-       ## If the path is echoed back, we most likely have an invalid data dir
-       if ($res =~ /$dir/) {
-               ndie msg('checkpoint-baddir2', $dir);
-       }
-
-       if ($res =~ /WARNING: Calculated CRC checksum/) {
-               ndie msg('checkpoint-badver');
-       }
-       if ($res !~ /^pg_control.+\d+/) {
-               ndie msg('checkpoint-badver2');
-       }
-
-       my $regex = msg('checkpoint-po');
-       if ($res !~ /$regex\s*(.+)/) { ## no critic (ProhibitUnusedCapture)
-               ## Just in case, check the English one as well
-               $regex = msg_en('checkpoint-po');
-               if ($res !~ /$regex\s*(.+)/) {
-                       ndie msg('checkpoint-noregex', $dir);
-               }
-       }
-       my $last = $1;
-
-       ## Convert to number of seconds
-       eval {
-               require Date::Parse;
-               import Date::Parse;
-       };
-       if ($@) {
-               ndie msg('checkpoint-nodp');
-       }
-       my $dt = str2time($last);
-       if ($dt !~ /^\d+$/) {
-               ndie msg('checkpoint-noparse', $last);
-       }
-       my $diff = $db->{perf} = time - $dt;
-       my $msg = $diff==1 ? msg('checkpoint-ok') : msg('checkpoint-ok2', $diff);
-
-       if ($MRTG) {
-               do_mrtg({one => $diff, msg => $msg});
-       }
-
-       if (length $critical and $diff >= $critical) {
-               add_critical $msg;
-               return;
-       }
-
-       if (length $warning and $diff >= $warning) {
-               add_warning $msg;
-               return;
-       }
-
-       add_ok $msg;
-
-       return;
+    ## Checks how long in seconds since the last checkpoint on a WAL slave
+    ## Supports: Nagios, MRTG
+    ## Warning and critical are seconds
+    ## Requires $ENV{PGDATA} or --datadir
+
+    my ($warning, $critical) = validate_range
+        ({
+          type              => 'time',
+          leastone          => 1,
+          forcemrtg         => 1,
+    });
+
+    ## Find the data directory, make sure it exists
+    my $dir = $opt{datadir} || $ENV{PGDATA};
+
+    if (!defined $dir or ! length $dir) {
+        ndie msg('checkpoint-nodir');
+    }
+
+    if (! -d $dir) {
+        ndie msg('checkpoint-baddir', $dir);
+    }
+
+    $db->{host} = '<none>';
+
+    ## Run pg_controldata, grab the time
+    my $pgc
+        = $ENV{PGCONTROLDATA} ? $ENV{PGCONTROLDATA}
+        : $ENV{PGBINDIR}      ? "$ENV{PGBINDIR}/pg_controldata"
+        :                       'pg_controldata';
+    $COM = qq{$pgc "$dir"};
+    eval {
+        $res = qx{$COM 2>&1};
+    };
+    if ($@) {
+        ndie msg('checkpoint-nosys', $@);
+    }
+
+    ## If the path is echoed back, we most likely have an invalid data dir
+    if ($res =~ /$dir/) {
+        ndie msg('checkpoint-baddir2', $dir);
+    }
+
+    if ($res =~ /WARNING: Calculated CRC checksum/) {
+        ndie msg('checkpoint-badver');
+    }
+    if ($res !~ /^pg_control.+\d+/) {
+        ndie msg('checkpoint-badver2');
+    }
+
+    my $regex = msg('checkpoint-po');
+    if ($res !~ /$regex\s*(.+)/) { ## no critic (ProhibitUnusedCapture)
+        ## Just in case, check the English one as well
+        $regex = msg_en('checkpoint-po');
+        if ($res !~ /$regex\s*(.+)/) {
+            ndie msg('checkpoint-noregex', $dir);
+        }
+    }
+    my $last = $1;
+
+    ## Convert to number of seconds
+    eval {
+        require Date::Parse;
+        import Date::Parse;
+    };
+    if ($@) {
+        ndie msg('checkpoint-nodp');
+    }
+    my $dt = str2time($last);
+    if ($dt !~ /^\d+$/) {
+        ndie msg('checkpoint-noparse', $last);
+    }
+    my $diff = $db->{perf} = time - $dt;
+    my $msg = $diff==1 ? msg('checkpoint-ok') : msg('checkpoint-ok2', $diff);
+
+    if ($MRTG) {
+        do_mrtg({one => $diff, msg => $msg});
+    }
+
+    if (length $critical and $diff >= $critical) {
+        add_critical $msg;
+        return;
+    }
+
+    if (length $warning and $diff >= $warning) {
+        add_warning $msg;
+        return;
+    }
+
+    add_ok $msg;
+
+    return;
 
 } ## end of check_checkpoint
 
 
 sub check_connection {
 
-       ## Check the connection, get the connection time and version
-       ## No comparisons made: warning and critical are not allowed
-       ## Suports: Nagios, MRTG
+    ## Check the connection, get the connection time and version
+    ## No comparisons made: warning and critical are not allowed
+    ## Suports: Nagios, MRTG
 
-       if ($opt{warning} or $opt{critical}) {
-               ndie msg('range-none');
-       }
+    if ($opt{warning} or $opt{critical}) {
+        ndie msg('range-none');
+    }
 
-       my $info = run_command('SELECT version() AS v');
+    my $info = run_command('SELECT version() AS v');
 
-       $db = $info->{db}[0];
+    $db = $info->{db}[0];
 
-       my $ver = ($db->{slurp}[0]{v} =~ /PostgreSQL (\d+\.\d+\S+)/o) ? $1 : '';
+    my $ver = ($db->{slurp}[0]{v} =~ /PostgreSQL (\d+\.\d+\S+)/o) ? $1 : '';
 
-       $MRTG and do_mrtg({one => $ver ? 1 : 0});
+    $MRTG and do_mrtg({one => $ver ? 1 : 0});
 
-       if ($ver) {
-               add_ok msg('version', $ver);
-       }
-       else {
-               add_unknown msg('invalid-query', $db->{slurp}[0]{v});
-       }
+    if ($ver) {
+        add_ok msg('version', $ver);
+    }
+    else {
+        add_unknown msg('invalid-query', $db->{slurp}[0]{v});
+    }
 
-       return;
+    return;
 
 } ## end of check_connection
 
 
 sub check_custom_query {
 
-       ## Run a user-supplied query, then parse the results
-       ## If you end up using this to make a useful query, consider making it
-       ## into a specific action and sending in a patch!
-       ## valtype must be one of: string, time, size, integer
+    ## Run a user-supplied query, then parse the results
+    ## If you end up using this to make a useful query, consider making it
+    ## into a specific action and sending in a patch!
+    ## valtype must be one of: string, time, size, integer
 
-       my $valtype = $opt{valtype} || 'integer';
+    my $valtype = $opt{valtype} || 'integer';
 
-       my ($warning, $critical) = validate_range({type => $valtype, leastone => 1});
+    my ($warning, $critical) = validate_range({type => $valtype, leastone => 1});
 
-       my $query = $opt{query} or ndie msg('custom-nostring');
+    my $query = $opt{query} or ndie msg('custom-nostring');
 
-       my $reverse = $opt{reverse} || 0;
+    my $reverse = $opt{reverse} || 0;
 
-       my $info = run_command($query);
+    my $info = run_command($query);
 
-       for $db (@{$info->{db}}) {
+    for $db (@{$info->{db}}) {
 
-               if (! @{$db->{slurp}}) {
-                       add_unknown msg('custom-norows');
-                       next;
-               }
+        if (! @{$db->{slurp}}) {
+            add_unknown msg('custom-norows');
+            next;
+        }
 
-               my $goodrow = 0;
+        my $goodrow = 0;
 
-               for my $r (@{$db->{slurp}}) {
-                       my ($data,$msg) = ($r->{result}, $r->{data}||'');
-                       $goodrow++;
-                       $db->{perf} .= " $msg";
-                       my $gotmatch = 0;
-                       if (length $critical) {
-                               if (($valtype eq 'string' and $data eq $critical)
-                                       or
-                                       ($reverse ? $data <= $critical : $data >= $critical)) { ## covers integer, time, size
-                                       add_critical "$data";
-                                       $gotmatch = 1;
-                               }
-                       }
+        for my $r (@{$db->{slurp}}) {
+            my ($data,$msg) = ($r->{result}, $r->{data}||'');
+            $goodrow++;
+            $db->{perf} .= " $msg";
+            my $gotmatch = 0;
+            if (length $critical) {
+                if (($valtype eq 'string' and $data eq $critical)
+                    or
+                    ($reverse ? $data <= $critical : $data >= $critical)) { ## covers integer, time, size
+                    add_critical "$data";
+                    $gotmatch = 1;
+                }
+            }
 
-                       if (length $warning and ! $gotmatch) {
-                               if (($valtype eq 'string' and $data eq $warning)
-                                       or
-                                       ($reverse ? $data <= $warning : $data >= $warning)) {
-                                       add_warning "$data";
-                                       $gotmatch = 1;
-                               }
-                       }
+            if (length $warning and ! $gotmatch) {
+                if (($valtype eq 'string' and $data eq $warning)
+                    or
+                    ($reverse ? $data <= $warning : $data >= $warning)) {
+                    add_warning "$data";
+                    $gotmatch = 1;
+                }
+            }
 
-                       if (! $gotmatch) {
-                               add_ok "$data";
-                       }
+            if (! $gotmatch) {
+                add_ok "$data";
+            }
 
-               } ## end each row returned
+        } ## end each row returned
 
-               if (!$goodrow) {
-                       add_unknown msg('custom-invalid');
-               }
-       }
+        if (!$goodrow) {
+            add_unknown msg('custom-invalid');
+        }
+    }
 
-       return;
+    return;
 
 } ## end of check_custom_query
 
 
 sub check_database_size {
 
-       ## Check the size of one or more databases
-       ## Supports: Nagios, MRTG
-       ## mrtg reports the largest two databases
-       ## By default, checks all databases
-       ## Can check specific one(s) with include
-       ## Can ignore some with exclude
-       ## Warning and critical are bytes
-       ## Valid units: b, k, m, g, t, e
-       ## All above may be written as plural or with a trailing 'b'
-       ## Limit to a specific user (db owner) with the includeuser option
-       ## Exclude users with the excludeuser option
+    ## Check the size of one or more databases
+    ## Supports: Nagios, MRTG
+    ## mrtg reports the largest two databases
+    ## By default, checks all databases
+    ## Can check specific one(s) with include
+    ## Can ignore some with exclude
+    ## Warning and critical are bytes
+    ## Valid units: b, k, m, g, t, e
+    ## All above may be written as plural or with a trailing 'b'
+    ## Limit to a specific user (db owner) with the includeuser option
+    ## Exclude users with the excludeuser option
 
-       my ($warning, $critical) = validate_range({type => 'size'});
+    my ($warning, $critical) = validate_range({type => 'size'});
 
-       $USERWHERECLAUSE =~ s/AND/WHERE/;
+    $USERWHERECLAUSE =~ s/AND/WHERE/;
 
-       $SQL = qq{
+    $SQL = qq{
 SELECT pg_database_size(d.oid) AS dsize,
   pg_size_pretty(pg_database_size(d.oid)) AS pdsize,
   datname,
@@ -3145,87 +3145,87 @@ SELECT pg_database_size(d.oid) AS dsize,
 FROM pg_database d
 JOIN pg_user u ON (u.usesysid=d.datdba)$USERWHERECLAUSE
 };
-       if ($opt{perflimit}) {
-               $SQL .= " ORDER BY 1 DESC LIMIT $opt{perflimit}";
-       }
-
-       my $info = run_command($SQL, { regex => qr{\d+}, emptyok => 1, } );
-       my $found = 0;
-
-       for $db (@{$info->{db}}) {
-               my $max = -1;
-               $found = 1;
-               my %s;
-               for my $r (@{$db->{slurp}}) {
-
-                       next if skip_item($r->{datname});
-
-                       if ($r->{dsize} >= $max) {
-                               $max = $r->{dsize};
-                       }
-                       $s{$r->{datname}} = [$r->{dsize},$r->{pdsize}];
-               }
-
-               if ($MRTG) {
-                       $stats{$db->{dbname}} = $max;
-                       next;
-               }
-               if ($max < 0) {
-                       $stats{$db->{dbname}} = 0;
-                       if ($USERWHERECLAUSE) {
-                               add_ok msg('no-match-user');
-                       }
-                       else {
-                               add_unknown msg('no-match-db');
-                       }
-                       next;
-               }
-
-               my $msg = '';
-               for (sort {$s{$b}[0] <=> $s{$a}[0] or $a cmp $b } keys %s) {
-                       $msg .= "$_: $s{$_}[0] ($s{$_}[1]) ";
-                       $db->{perf} .= " $_=$s{$_}[0]";
-               }
-               if (length $critical and $max >= $critical) {
-                       add_critical $msg;
-               }
-               elsif (length $warning and $max >= $warning) {
-                       add_warning $msg;
-               }
-               else {
-                       add_ok $msg;
-               }
-       }
-
-       ## If no results, probably a version problem
-       if (!$found and keys %unknown) {
-               (my $first) = values %unknown;
-               if ($first->[0][0] =~ /pg_database_size/) {
-                       ndie msg('dbsize-version');
-               }
-       }
-
-       return;
+    if ($opt{perflimit}) {
+        $SQL .= " ORDER BY 1 DESC LIMIT $opt{perflimit}";
+    }
+
+    my $info = run_command($SQL, { regex => qr{\d+}, emptyok => 1, } );
+    my $found = 0;
+
+    for $db (@{$info->{db}}) {
+        my $max = -1;
+        $found = 1;
+        my %s;
+        for my $r (@{$db->{slurp}}) {
+
+            next if skip_item($r->{datname});
+
+            if ($r->{dsize} >= $max) {
+                $max = $r->{dsize};
+            }
+            $s{$r->{datname}} = [$r->{dsize},$r->{pdsize}];
+        }
+
+        if ($MRTG) {
+            $stats{$db->{dbname}} = $max;
+            next;
+        }
+        if ($max < 0) {
+            $stats{$db->{dbname}} = 0;
+            if ($USERWHERECLAUSE) {
+                add_ok msg('no-match-user');
+            }
+            else {
+                add_unknown msg('no-match-db');
+            }
+            next;
+        }
+
+        my $msg = '';
+        for (sort {$s{$b}[0] <=> $s{$a}[0] or $a cmp $b } keys %s) {
+            $msg .= "$_: $s{$_}[0] ($s{$_}[1]) ";
+            $db->{perf} .= " $_=$s{$_}[0]";
+        }
+        if (length $critical and $max >= $critical) {
+            add_critical $msg;
+        }
+        elsif (length $warning and $max >= $warning) {
+            add_warning $msg;
+        }
+        else {
+            add_ok $msg;
+        }
+    }
+
+    ## If no results, probably a version problem
+    if (!$found and keys %unknown) {
+        (my $first) = values %unknown;
+        if ($first->[0][0] =~ /pg_database_size/) {
+            ndie msg('dbsize-version');
+        }
+    }
+
+    return;
 
 } ## end of check_database_size
 
 
 sub show_dbstats {
 
-       ## Returns values from the pg_stat_database view
-       ## Supports: Cacti
-       ## Assumes psql and target are the same version for the 8.3 check
+    ## Returns values from the pg_stat_database view
+    ## Supports: Cacti
+    ## Assumes psql and target are the same version for the 8.3 check
 
-       my ($warning, $critical) = validate_range
-               ({
-                 type => 'cacti',
-       });
+    my ($warning, $critical) = validate_range
+        ({
+          type => 'cacti',
+    });
 
-       my $SQL = q{SELECT datname,
+    my $SQL = q{SELECT datname,
   numbackends AS backends,xact_commit AS commits,xact_rollback AS rollbacks,
   blks_read AS read, blks_hit AS hit};
-       if ($opt{dbname}) {
-               $SQL .= q{
+    if ($opt{dbname}) {
+        $SQL .= q{
  ,(SELECT SUM(idx_scan) FROM pg_stat_user_indexes) AS idxscan
  ,COALESCE((SELECT SUM(idx_tup_read) FROM pg_stat_user_indexes),0) AS idxtupread
  ,COALESCE((SELECT SUM(idx_tup_fetch) FROM pg_stat_user_indexes),0) AS idxtupfetch
@@ -3234,132 +3234,132 @@ sub show_dbstats {
  ,COALESCE((SELECT SUM(seq_scan) FROM pg_stat_user_tables),0) AS seqscan
  ,COALESCE((SELECT SUM(seq_tup_read) FROM pg_stat_user_tables),0) AS seqtupread
 };
-       }
-       $SQL .= q{ FROM pg_stat_database};
-       (my $SQL2 = $SQL) =~ s/AS seq_tup_read/AS seq_tup_read, tup_returned AS ret, tup_fetched AS fetch, tup_inserted AS ins, tup_updated AS upd, tup_deleted AS del/;
+    }
+    $SQL .= q{ FROM pg_stat_database};
+    (my $SQL2 = $SQL) =~ s/AS seq_tup_read/AS seq_tup_read, tup_returned AS ret, tup_fetched AS fetch, tup_inserted AS ins, tup_updated AS upd, tup_deleted AS del/;
 
-       my $info = run_command($SQL, {regex => qr{\w}, version => [ ">8.2 $SQL2" ] } );
+    my $info = run_command($SQL, {regex => qr{\w}, version => [ ">8.2 $SQL2" ] } );
 
-       for $db (@{$info->{db}}) {
-         ROW: for my $r (@{$db->{slurp}}) {
+    for $db (@{$info->{db}}) {
+      ROW: for my $r (@{$db->{slurp}}) {
 
-                       my $dbname = $r->{datname};
+            my $dbname = $r->{datname};
 
-                       next ROW if skip_item($dbname);
+            next ROW if skip_item($dbname);
 
-                       ## If dbnames were specififed, use those for filtering as well
-                       if (@{$opt{dbname}}) {
-                               my $keepit = 0;
-                               for my $drow (@{$opt{dbname}}) {
-                                       for my $d (split /,/ => $drow) {
-                                               $d eq $dbname and $keepit = 1;
-                                       }
-                               }
-                               next ROW unless $keepit;
-                       }
+            ## If dbnames were specififed, use those for filtering as well
+            if (@{$opt{dbname}}) {
+                my $keepit = 0;
+                for my $drow (@{$opt{dbname}}) {
+                    for my $d (split /,/ => $drow) {
+                        $d eq $dbname and $keepit = 1;
+                    }
+                }
+                next ROW unless $keepit;
+            }
 
-                       my $msg = '';
-                       for my $col (qw/
+            my $msg = '';
+            for my $col (qw/
 backends commits rollbacks
 read hit
 idxscan idxtupread idxtupfetch idxblksread idxblkshit
 seqscan seqtupread
 ret fetch ins upd del/) {
-                               $msg .= "$col:";
-                               $msg .= (exists $r->{$col} and length $r->{$col}) ? $r->{$col} : 0;
-                               $msg .=  ' ';
-                       }
-                       print "${msg}dbname:$dbname\n";
-               }
-       }
+                $msg .= "$col:";
+                $msg .= (exists $r->{$col} and length $r->{$col}) ? $r->{$col} : 0;
+                $msg .=  ' ';
+            }
+            print "${msg}dbname:$dbname\n";
+        }
+    }
 
-       exit 0;
+    exit 0;
 
 } ## end of show_dbstats
 
 
 sub check_disabled_triggers {
 
-       ## Checks how many disabled triggers are in the database
-       ## Supports: Nagios, MRTG
-       ## Warning and critical are integers, defaults to 1
+    ## Checks how many disabled triggers are in the database
+    ## Supports: Nagios, MRTG
+    ## Warning and critical are integers, defaults to 1
 
-       my ($warning, $critical) = validate_range
-               ({
-                 type              => 'positive integer',
-                 default_warning   => 1,
-                 default_critical  => 1,
-                 forcemrtg         => 1,
-       });
+    my ($warning, $critical) = validate_range
+        ({
+          type              => 'positive integer',
+          default_warning   => 1,
+          default_critical  => 1,
+          forcemrtg         => 1,
+    });
 
-       $SQL = q{
+    $SQL = q{
 SELECT tgrelid::regclass AS tname, tgname, tgenabled
 FROM pg_trigger
 WHERE tgenabled IS NOT TRUE ORDER BY tgname
 };
-       my $SQL83 = q{
+    my $SQL83 = q{
 SELECT tgrelid::regclass AS tname, tgname, tgenabled
 FROM pg_trigger
 WHERE tgenabled = 'D' ORDER BY tgname
 };
-       my $SQLOLD = q{SELECT 'FAIL' AS fail};
+    my $SQLOLD = q{SELECT 'FAIL' AS fail};
 
-       my $info = run_command($SQL, { version => [ ">8.2 $SQL83", "<8.1 $SQLOLD" ] } );
+    my $info = run_command($SQL, { version => [ ">8.2 $SQL83", "<8.1 $SQLOLD" ] } );
 
-       if (exists $info->{db}[0]{fail}) {
-               ndie msg('die-action-version', $action, '8.1', $db->{version});
-       }
+    if (exists $info->{db}[0]{fail}) {
+        ndie msg('die-action-version', $action, '8.1', $db->{version});
+    }
 
-       my $count = 0;
-       my $dislis = '';
-       for $db (@{$info->{db}}) {
+    my $count = 0;
+    my $dislis = '';
+    for $db (@{$info->{db}}) {
 
-         ROW: for my $r (@{$db->{slurp}}) {
-                       $count++;
-                       $dislis .= " $r->{tname}=>$r->{tgname}";
-               }
-               $MRTG and do_mrtg({one => $count});
+      ROW: for my $r (@{$db->{slurp}}) {
+            $count++;
+            $dislis .= " $r->{tname}=>$r->{tgname}";
+        }
+        $MRTG and do_mrtg({one => $count});
 
-               my $msg = msg('trigger-msg', "$count$dislis");
+        my $msg = msg('trigger-msg', "$count$dislis");
 
-               if ($critical and $count >= $critical) {
-                       add_critical $msg;
-               }
-               elsif ($warning and $count >= $warning) {
-                       add_warning $msg;
-               }
-               else {
-                       add_ok $msg;
-               }
-       }
+        if ($critical and $count >= $critical) {
+            add_critical $msg;
+        }
+        elsif ($warning and $count >= $warning) {
+            add_warning $msg;
+        }
+        else {
+            add_ok $msg;
+        }
+    }
 
-       return;
+    return;
 
 } ## end of check_disabled_triggers
 
 
 sub check_disk_space {
 
-       ## Check the available disk space used by postgres
-       ## Supports: Nagios, MRTG
-       ## Requires the executable "/bin/df"
-       ## Must run as a superuser in the database (to examine 'data_directory' setting)
-       ## Critical and warning are maximum size, or percentages
-       ## Example: --critical="40 GB"
-       ## NOTE: Needs to run on the same system (for now)
-       ## XXX Allow custom ssh commands for remote df and the like
-
-       my ($warning, $critical) = validate_range
-               ({
-                 type             => 'size or percent',
-                 default_warning  => '90%',
-                 default_critical => '95%',
-                 });
-
-       -x '/bin/df' or ndie msg('diskspace-nodf');
-
-       ## Figure out where everything is.
-       $SQL = q{
+    ## Check the available disk space used by postgres
+    ## Supports: Nagios, MRTG
+    ## Requires the executable "/bin/df"
+    ## Must run as a superuser in the database (to examine 'data_directory' setting)
+    ## Critical and warning are maximum size, or percentages
+    ## Example: --critical="40 GB"
+    ## NOTE: Needs to run on the same system (for now)
+    ## XXX Allow custom ssh commands for remote df and the like
+
+    my ($warning, $critical) = validate_range
+        ({
+          type             => 'size or percent',
+          default_warning  => '90%',
+          default_critical => '95%',
+          });
+
+    -x '/bin/df' or ndie msg('diskspace-nodf');
+
+    ## Figure out where everything is.
+    $SQL = q{
 SELECT 'S' AS syn, name AS nn, setting AS val
 FROM pg_settings
 WHERE name = 'data_directory'
@@ -3370,178 +3370,178 @@ FROM pg_tablespace
 WHERE spclocation <> ''
 };
 
-       my $info = run_command($SQL);
-
-       my %dir; ## 1 = normal 2 = been checked -1 = does not exist
-       my %seenfs;
-       for $db (@{$info->{db}}) {
-               my %i;
-               for my $r (@{$db->{slurp}}) {
-                       $i{$r->{syn}}{$r->{nn}} = $r->{val};
-               }
-               if (! exists $i{S}{data_directory}) {
-                       add_unknown msg('diskspace-nodata');
-                       next;
-               }
-               my ($datadir,$logdir) = ($i{S}{data_directory},$i{S}{log_directory}||'');
-
-               if (!exists $dir{$datadir}) {
-                       if (! -d $datadir) {
-                               add_unknown msg('diskspace-nodir', $datadir);
-                               $dir{$datadir} = -1;
-                               next;
-                       }
-                       $dir{$datadir} = 1;
-
-                       ## Check if the WAL files are on a separate disk
-                       my $xlog = "$datadir/pg_xlog";
-                       if (-l $xlog) {
-                               my $linkdir = readlink($xlog);
-                               $dir{$linkdir} = 1 if ! exists $dir{$linkdir};
-                       }
-               }
-
-               ## Check log_directory: relative or absolute
-               if (length $logdir) {
-                       if ($logdir =~ /^\w/) { ## relative, check only if symlinked
-                               $logdir = "$datadir/$logdir";
-                               if (-l $logdir) {
-                                       my $linkdir = readlink($logdir);
-                                       $dir{$linkdir} = 1 if ! exists $dir{$linkdir};
-                               }
-                       }
-                       else { ## absolute, always check
-                               if ($logdir ne $datadir and ! exists $dir{$logdir}) {
-                                       $dir{$logdir} = 1;
-                               }
-                       }
-               }
-
-               ## Check all tablespaces
-               for my $tsname (keys %{$i{T}}) {
-                       my $tsdir = $i{T}{$tsname};
-                       $dir{$tsdir} = 1 if ! exists $dir{$tsdir};
-               }
-
-               my $gotone = 0;
-               for my $dir (keys %dir) {
-                       next if $dir{$dir} != 1;
-
-                       $dir{$dir} = 1;
-
-                       $COM = qq{/bin/df -kP "$dir" 2>&1};
-                       $res = qx{$COM};
-
-                       if ($res !~ /^.+\n(\S+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\%\s+(\S+)/) {
-                               ndie msg('diskspace-fail', $COM, $res);
-                       }
-                       my ($fs,$total,$used,$avail,$percent,$mount) = ($1,$2*1024,$3*1024,$4*1024,$5,$6);
-
-                       ## If we've already done this one, skip it
-                       next if $seenfs{$fs}++;
-
-                       next if skip_item($fs);
-
-                       if ($MRTG) {
-                               $stats{$fs} = [$total,$used,$avail,$percent];
-                               next;
-                       }
-
-                       $gotone = 1;
-
-                       ## Rather than make another call with -h, do it ourselves
-                       my $prettyused = pretty_size($used);
-                       my $prettytotal = pretty_size($total);
-
-                       my $msg = msg('diskspace-msg', $fs, $mount, $prettyused, $prettytotal, $percent);
-
-                       $db->{perf} = "$fs=$used";
-
-                       my $ok = 1;
-                       if (length $critical) {
-                               if (index($critical,'%')>=0) {
-                                       (my $critical2 = $critical) =~ s/\%//;
-                                       if ($percent >= $critical2) {
-                                               add_critical $msg;
-                                               $ok = 0;
-                                       }
-                               }
-                               elsif ($used >= $critical) {
-                                       add_critical $msg;
-                                       $ok = 0;
-                               }
-                       }
-                       if (length $warning and $ok) {
-                               if (index($warning,'%')>=0) {
-                                       (my $warning2 = $warning) =~ s/\%//;
-                                       if ($percent >= $warning2) {
-                                               add_warning $msg;
-                                               $ok = 0;
-                                       }
-                               }
-                               elsif ($used >= $warning) {
-                                       add_warning $msg;
-                                       $ok = 0;
-                               }
-                       }
-                       if ($ok) {
-                               add_ok $msg;
-                       }
-               } ## end each dir
-
-               next if $MRTG;
-
-               if (!$gotone) {
-                       add_unknown msg('no-match-fs');
-               }
-       }
-
-       if ($MRTG) {
-               keys %stats or bad_mrtg(msg('unknown-error'));
-               ## Get the highest by total size or percent (total, used, avail, percent)
-               ## We default to 'available'
-               my $sortby = exists $opt{mrtg}
-                       ? $opt{mrtg} eq 'total'   ? 0
-                       : $opt{mrtg} eq 'used'    ? 1
-                       : $opt{mrtg} eq 'avail'   ? 2
-                       : $opt{mrtg} eq 'percent' ? 3 : 2 : 2;
-               my ($one,$two,$msg) = ('','','');
-               for (sort { $stats{$b}->[$sortby] <=> $stats{$a}->[$sortby] } keys %stats) {
-                       if ($one eq '') {
-                               $one = $stats{$_}->[$sortby];
-                               $msg = $_;
-                               next;
-                       }
-                       $two = $stats{$_}->[$sortby];
-                       last;
-               }
-               do_mrtg({one => $one, two => $two, msg => $msg});
-       }
-
-       return;
+    my $info = run_command($SQL);
+
+    my %dir; ## 1 = normal 2 = been checked -1 = does not exist
+    my %seenfs;
+    for $db (@{$info->{db}}) {
+        my %i;
+        for my $r (@{$db->{slurp}}) {
+            $i{$r->{syn}}{$r->{nn}} = $r->{val};
+        }
+        if (! exists $i{S}{data_directory}) {
+            add_unknown msg('diskspace-nodata');
+            next;
+        }
+        my ($datadir,$logdir) = ($i{S}{data_directory},$i{S}{log_directory}||'');
+
+        if (!exists $dir{$datadir}) {
+            if (! -d $datadir) {
+                add_unknown msg('diskspace-nodir', $datadir);
+                $dir{$datadir} = -1;
+                next;
+            }
+            $dir{$datadir} = 1;
+
+            ## Check if the WAL files are on a separate disk
+            my $xlog = "$datadir/pg_xlog";
+            if (-l $xlog) {
+                my $linkdir = readlink($xlog);
+                $dir{$linkdir} = 1 if ! exists $dir{$linkdir};
+            }
+        }
+
+        ## Check log_directory: relative or absolute
+        if (length $logdir) {
+            if ($logdir =~ /^\w/) { ## relative, check only if symlinked
+                $logdir = "$datadir/$logdir";
+                if (-l $logdir) {
+                    my $linkdir = readlink($logdir);
+                    $dir{$linkdir} = 1 if ! exists $dir{$linkdir};
+                }
+            }
+            else { ## absolute, always check
+                if ($logdir ne $datadir and ! exists $dir{$logdir}) {
+                    $dir{$logdir} = 1;
+                }
+            }
+        }
+
+        ## Check all tablespaces
+        for my $tsname (keys %{$i{T}}) {
+            my $tsdir = $i{T}{$tsname};
+            $dir{$tsdir} = 1 if ! exists $dir{$tsdir};
+        }
+
+        my $gotone = 0;
+        for my $dir (keys %dir) {
+            next if $dir{$dir} != 1;
+
+            $dir{$dir} = 1;
+
+            $COM = qq{/bin/df -kP "$dir" 2>&1};
+            $res = qx{$COM};
+
+            if ($res !~ /^.+\n(\S+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\%\s+(\S+)/) {
+                ndie msg('diskspace-fail', $COM, $res);
+            }
+            my ($fs,$total,$used,$avail,$percent,$mount) = ($1,$2*1024,$3*1024,$4*1024,$5,$6);
+
+            ## If we've already done this one, skip it
+            next if $seenfs{$fs}++;
+
+            next if skip_item($fs);
+
+            if ($MRTG) {
+                $stats{$fs} = [$total,$used,$avail,$percent];
+                next;
+            }
+
+            $gotone = 1;
+
+            ## Rather than make another call with -h, do it ourselves
+            my $prettyused = pretty_size($used);
+            my $prettytotal = pretty_size($total);
+
+            my $msg = msg('diskspace-msg', $fs, $mount, $prettyused, $prettytotal, $percent);
+
+            $db->{perf} = "$fs=$used";
+
+            my $ok = 1;
+            if (length $critical) {
+                if (index($critical,'%')>=0) {
+                    (my $critical2 = $critical) =~ s/\%//;
+                    if ($percent >= $critical2) {
+                        add_critical $msg;
+                        $ok = 0;
+                    }
+                }
+                elsif ($used >= $critical) {
+                    add_critical $msg;
+                    $ok = 0;
+                }
+            }
+            if (length $warning and $ok) {
+                if (index($warning,'%')>=0) {
+                    (my $warning2 = $warning) =~ s/\%//;
+                    if ($percent >= $warning2) {
+                        add_warning $msg;
+                        $ok = 0;
+                    }
+                }
+                elsif ($used >= $warning) {
+                    add_warning $msg;
+                    $ok = 0;
+                }
+            }
+            if ($ok) {
+                add_ok $msg;
+            }
+        } ## end each dir
+
+        next if $MRTG;
+
+        if (!$gotone) {
+            add_unknown msg('no-match-fs');
+        }
+    }
+
+    if ($MRTG) {
+        keys %stats or bad_mrtg(msg('unknown-error'));
+        ## Get the highest by total size or percent (total, used, avail, percent)
+        ## We default to 'available'
+        my $sortby = exists $opt{mrtg}
+            ? $opt{mrtg} eq 'total'   ? 0
+            : $opt{mrtg} eq 'used'    ? 1
+            : $opt{mrtg} eq 'avail'   ? 2
+            : $opt{mrtg} eq 'percent' ? 3 : 2 : 2;
+        my ($one,$two,$msg) = ('','','');
+        for (sort { $stats{$b}->[$sortby] <=> $stats{$a}->[$sortby] } keys %stats) {
+            if ($one eq '') {
+                $one = $stats{$_}->[$sortby];
+                $msg = $_;
+                next;
+            }
+            $two = $stats{$_}->[$sortby];
+            last;
+        }
+        do_mrtg({one => $one, two => $two, msg => $msg});
+    }
+
+    return;
 
 } ## end of check_disk_space
 
 
 sub check_fsm_pages {
 
-       ## Check on the percentage of free space map pages in use
-       ## Supports: Nagios, MRTG
-       ## Must run as superuser
-       ## Requires pg_freespacemap contrib module
-       ## Critical and warning are a percentage of max_fsm_pages
-       ## Example: --critical=95
-
-       my ($warning, $critical) = validate_range
-               ({
-                 type              => 'percent',
-                 default_warning   => '85%',
-                 default_critical  => '95%',
-                 });
-
-       (my $w = $warning) =~ s/\D//;
-       (my $c = $critical) =~ s/\D//;
-       my $SQL = qq{
+    ## Check on the percentage of free space map pages in use
+    ## Supports: Nagios, MRTG
+    ## Must run as superuser
+    ## Requires pg_freespacemap contrib module
+    ## Critical and warning are a percentage of max_fsm_pages
+    ## Example: --critical=95
+
+    my ($warning, $critical) = validate_range
+        ({
+          type              => 'percent',
+          default_warning   => '85%',
+          default_critical  => '95%',
+          });
+
+    (my $w = $warning) =~ s/\D//;
+    (my $c = $critical) =~ s/\D//;
+    my $SQL = qq{
 SELECT pages, maxx, ROUND(100*(pages/maxx)) AS percent
 FROM 
   (SELECT (sumrequests+numrels)*chunkpages AS pages
@@ -3550,144 +3550,144 @@ FROM
      COUNT(relfilenode) AS numrels, 16 AS chunkpages FROM pg_freespacemap_relations) AS foo) AS foo2,
   (SELECT setting::NUMERIC AS maxx FROM pg_settings WHERE name = 'max_fsm_pages') AS foo3
 };
-       my $SQLNOOP = q{SELECT 'FAIL' AS fail};
+    my $SQLNOOP = q{SELECT 'FAIL' AS fail};
 
-       my $info = run_command($SQL, { version => [ ">8.3 $SQLNOOP" ] } );
+    my $info = run_command($SQL, { version => [ ">8.3 $SQLNOOP" ] } );
 
-       if (exists $info->{db}[0]{fail}) {
-               add_unknown msg('fsm-page-highver');
-               return;
-       }
+    if (exists $info->{db}[0]{fail}) {
+        add_unknown msg('fsm-page-highver');
+        return;
+    }
 
-       for $db (@{$info->{db}}) {
-               for my $r (@{$db->{slurp}}) {
-                       my ($pages,$max,$percent) = ($r->{pages}||0,$r->{maxx},$r->{percent}||0);
+    for $db (@{$info->{db}}) {
+        for my $r (@{$db->{slurp}}) {
+            my ($pages,$max,$percent) = ($r->{pages}||0,$r->{maxx},$r->{percent}||0);
 
-                       $MRTG and do_mrtg({one => $percent, two => $pages});
+            $MRTG and do_mrtg({one => $percent, two => $pages});
 
-                       my $msg = msg('fsm-page-msg', $pages, $max, $percent);
+            my $msg = msg('fsm-page-msg', $pages, $max, $percent);
 
-                       if (length $critical and $percent >= $c) {
-                               add_critical $msg;
-                       }
-                       elsif (length $warning and $percent >= $w) {
-                               add_warning $msg;
-                       }
-                       else {
-                               add_ok $msg;
-                       }
-               }
-       }
+            if (length $critical and $percent >= $c) {
+                add_critical $msg;
+            }
+            elsif (length $warning and $percent >= $w) {
+                add_warning $msg;
+            }
+            else {
+                add_ok $msg;
+            }
+        }
+    }
 
-       return;
+    return;
 
 } ## end of check_fsm_pages
 
 
 sub check_fsm_relations {
 
-       ## Check on the % of free space map relations in use
-       ## Supports: Nagios, MRTG
-       ## Must run as superuser
-       ## Requires pg_freespacemap contrib module
-       ## Critical and warning are a percentage of max_fsm_relations
-       ## Example: --critical=95
+    ## Check on the % of free space map relations in use
+    ## Supports: Nagios, MRTG
+    ## Must run as superuser
+    ## Requires pg_freespacemap contrib module
+    ## Critical and warning are a percentage of max_fsm_relations
+    ## Example: --critical=95
 
-       my ($warning, $critical) = validate_range
-               ({
-                 type              => 'percent',
-                 default_warning   => '85%',
-                 default_critical  => '95%',
-                 });
+    my ($warning, $critical) = validate_range
+        ({
+          type              => 'percent',
+          default_warning   => '85%',
+          default_critical  => '95%',
+          });
 
-       (my $w = $warning) =~ s/\D//;
-       (my $c = $critical) =~ s/\D//;
+    (my $w = $warning) =~ s/\D//;
+    (my $c = $critical) =~ s/\D//;
 
-       my $SQL = qq{
+    my $SQL = qq{
 SELECT maxx, cur, ROUND(100*(cur/maxx)) AS percent
 FROM (SELECT 
     (SELECT COUNT(*) FROM pg_freespacemap_relations) AS cur,
     (SELECT setting::NUMERIC FROM pg_settings WHERE name='max_fsm_relations') AS maxx) x
 };
-       my $SQLNOOP = q{SELECT 'FAIL' AS fail};
+    my $SQLNOOP = q{SELECT 'FAIL' AS fail};
 
-       my $info = run_command($SQL, { version => [ ">8.3 $SQLNOOP" ] } );
+    my $info = run_command($SQL, { version => [ ">8.3 $SQLNOOP" ] } );
 
-       if (exists $info->{db}[0]{fail}) {
-               add_unknown msg('fsm-rel-highver');
-               return;
-       }
+    if (exists $info->{db}[0]{fail}) {
+        add_unknown msg('fsm-rel-highver');
+        return;
+    }
 
-       for $db (@{$info->{db}}) {
+    for $db (@{$info->{db}}) {
 
-               for my $r (@{$db->{slurp}}) {
-                       my ($max,$cur,$percent) = ($r->{maxx},$r->{cur},$r->{percent});
+        for my $r (@{$db->{slurp}}) {
+            my ($max,$cur,$percent) = ($r->{maxx},$r->{cur},$r->{percent});
 
-                       $MRTG and do_mrtg({one => $percent, two => $cur});
+            $MRTG and do_mrtg({one => $percent, two => $cur});
 
-                       my $msg = msg('fsm-rel-msg', $cur, $max, $percent);
+            my $msg = msg('fsm-rel-msg', $cur, $max, $percent);
 
-                       if (length $critical and $percent >= $c) {
-                               add_critical $msg;
-                       }
-                       elsif (length $warning and $percent >= $w) {
-                               add_warning $msg;
-                       }
-                       else {
-                               add_ok $msg;
-                       }
-               }
+            if (length $critical and $percent >= $c) {
+                add_critical $msg;
+            }
+            elsif (length $warning and $percent >= $w) {
+                add_warning $msg;
+            }
+            else {
+                add_ok $msg;
+            }
+        }
 
-       }
+    }
 
-       return;
+    return;
 
 } ## end of check_fsm_relations
 
 
 sub check_last_analyze {
-       my $auto = shift || '';
-       return check_last_vacuum_analyze('analyze', $auto);
+    my $auto = shift || '';
+    return check_last_vacuum_analyze('analyze', $auto);
 }
 
 
 sub check_last_vacuum {
-       my $auto = shift || '';
-       return check_last_vacuum_analyze('vacuum', $auto);
+    my $auto = shift || '';
+    return check_last_vacuum_analyze('vacuum', $auto);
 }
 
 
 sub check_last_vacuum_analyze {
 
-       my $type = shift || 'vacuum';
-       my $auto = shift || 0;
-
-       ## Check the last time things were vacuumed or analyzed
-       ## Supports: Nagios, MRTG
-       ## NOTE: stats_row_level must be set to on in your database (if version 8.2)
-       ## By default, reports on the oldest value in the database
-       ## Can exclude and include tables
-       ## Warning and critical are times, default to seconds
-       ## Valid units: s[econd], m[inute], h[our], d[ay]
-       ## All above may be written as plural as well (e.g. "2 hours")
-       ## Limit to a specific user (relation owner) with the includeuser option
-       ## Exclude users with the excludeuser option
-       ## Example:
-       ## --exclude=~pg_ --include=pg_class,pg_attribute
-
-       my ($warning, $critical) = validate_range
-               ({
-                type              => 'time',
-                 default_warning  => '1 day',
-                 default_critical => '2 days',
-                 });
-
-       my $criteria = $auto ?
-               qq{pg_stat_get_last_auto${type}_time(c.oid)}
-                       : qq{GREATEST(pg_stat_get_last_${type}_time(c.oid), pg_stat_get_last_auto${type}_time(c.oid))};
-
-       ## Do include/exclude earlier for large pg_classes?
-       $SQL = qq{
+    my $type = shift || 'vacuum';
+    my $auto = shift || 0;
+
+    ## Check the last time things were vacuumed or analyzed
+    ## Supports: Nagios, MRTG
+    ## NOTE: stats_row_level must be set to on in your database (if version 8.2)
+    ## By default, reports on the oldest value in the database
+    ## Can exclude and include tables
+    ## Warning and critical are times, default to seconds
+    ## Valid units: s[econd], m[inute], h[our], d[ay]
+    ## All above may be written as plural as well (e.g. "2 hours")
+    ## Limit to a specific user (relation owner) with the includeuser option
+    ## Exclude users with the excludeuser option
+    ## Example:
+    ## --exclude=~pg_ --include=pg_class,pg_attribute
+
+    my ($warning, $critical) = validate_range
+        ({
+         type              => 'time',
+          default_warning  => '1 day',
+          default_critical => '2 days',
+          });
+
+    my $criteria = $auto ?
+        qq{pg_stat_get_last_auto${type}_time(c.oid)}
+            : qq{GREATEST(pg_stat_get_last_${type}_time(c.oid), pg_stat_get_last_auto${type}_time(c.oid))};
+
+    ## Do include/exclude earlier for large pg_classes?
+    $SQL = qq{
 SELECT current_database() AS datname, nspname AS sname, relname AS tname,
   CASE WHEN v IS NULL THEN -1 ELSE round(extract(epoch FROM now()-v)) END AS ltime,
   CASE WHEN v IS NULL THEN '?' ELSE TO_CHAR(v, '$SHOWTIME') END AS ptime
@@ -3698,593 +3698,593 @@ FROM (SELECT nspname, relname, $criteria AS v
       AND n.nspname <> 'information_schema'
       ORDER BY 3) AS foo
 };
-       if ($opt{perflimit}) {
-               $SQL .= ' ORDER BY 3 DESC';
-       }
-
-       if ($USERWHERECLAUSE) {
-               $SQL =~ s/ WHERE/, pg_user u WHERE u.usesysid=c.relowner$USERWHERECLAUSE AND/;
-       }
-
-       my $info = run_command($SQL, { regex => qr{\w}, emptyok => 1 } );
-
-       for $db (@{$info->{db}}) {
-
-               if (! @{$db->{slurp}} and $USERWHERECLAUSE) {
-                       $stats{$db->{dbname}} = 0;
-                       add_ok msg('no-match-user');
-                       return;
-               }
-
-               ## -1 means no tables found at all
-               ## -2 means exclusion rules took effect
-               ## -3 means no tables were ever vacuumed/analyzed
-               my $maxtime = -1;
-               my $maxptime = '?';
-               my ($minrel,$maxrel) = ('?','?'); ## no critic
-               my $mintime = 0; ## used for MRTG only
-               my $count = 0;
-         ROW: for my $r (@{$db->{slurp}}) {
-                       my ($dbname,$schema,$name,$time,$ptime) = @$r{qw/ datname sname tname ltime ptime/};
-                       $maxtime = -3 if $maxtime == -1;
-                       if (skip_item($name, $schema)) {
-                               $maxtime = -2 if $maxtime < 1;
-                               next ROW;
-                       }
-                       $db->{perf} .= " $dbname.$schema.$name=${time}s;$warning;$critical" if $time >= 0;
-                       if ($time > $maxtime) {
-                               $maxtime = $time;
-                               $maxrel = "$schema.$name";
-                               $maxptime = $ptime;
-                       }
-                       if ($time > 0 and ($time < $mintime or !$mintime)) {
-                               $mintime = $time;
-                               $minrel = "$schema.$name";
-                       }
-                       if ($opt{perflimit}) {
-                               last if ++$count >= $opt{perflimit};
-                       }
-               }
-               if ($MRTG) {
-                       $stats{$db->{dbname}} = $mintime;
-                       $statsmsg{$db->{dbname}} = msg('vac-msg', $db->{dbname}, $minrel);
-                       return;
-               }
-
-               if ($maxtime == -2) {
-                       add_unknown msg('no-match-table');
-               }
-               elsif ($maxtime < 0) {
-                       add_unknown $type eq 'vacuum' ? msg('vac-nomatch-v') : msg('vac-nomatch-a');
-               }
-               else {
-                       my $showtime = pretty_time($maxtime, 'S');
-                       my $msg = "$maxrel: $maxptime ($showtime)";
-                       if ($critical and $maxtime >= $critical) {
-                               add_critical $msg;
-                       }
-                       elsif ($warning and $maxtime >= $warning) {
-                               add_warning $msg;
-                       }
-                       else {
-                               add_ok $msg;
-                       }
-               }
-       }
-
-       return;
+    if ($opt{perflimit}) {
+        $SQL .= ' ORDER BY 3 DESC';
+    }
+
+    if ($USERWHERECLAUSE) {
+        $SQL =~ s/ WHERE/, pg_user u WHERE u.usesysid=c.relowner$USERWHERECLAUSE AND/;
+    }
+
+    my $info = run_command($SQL, { regex => qr{\w}, emptyok => 1 } );
+
+    for $db (@{$info->{db}}) {
+
+        if (! @{$db->{slurp}} and $USERWHERECLAUSE) {
+            $stats{$db->{dbname}} = 0;
+            add_ok msg('no-match-user');
+            return;
+        }
+
+        ## -1 means no tables found at all
+        ## -2 means exclusion rules took effect
+        ## -3 means no tables were ever vacuumed/analyzed
+        my $maxtime = -1;
+        my $maxptime = '?';
+        my ($minrel,$maxrel) = ('?','?'); ## no critic
+        my $mintime = 0; ## used for MRTG only
+        my $count = 0;
+      ROW: for my $r (@{$db->{slurp}}) {
+            my ($dbname,$schema,$name,$time,$ptime) = @$r{qw/ datname sname tname ltime ptime/};
+            $maxtime = -3 if $maxtime == -1;
+            if (skip_item($name, $schema)) {
+                $maxtime = -2 if $maxtime < 1;
+                next ROW;
+            }
+            $db->{perf} .= " $dbname.$schema.$name=${time}s;$warning;$critical" if $time >= 0;
+            if ($time > $maxtime) {
+                $maxtime = $time;
+                $maxrel = "$schema.$name";
+                $maxptime = $ptime;
+            }
+            if ($time > 0 and ($time < $mintime or !$mintime)) {
+                $mintime = $time;
+                $minrel = "$schema.$name";
+            }
+            if ($opt{perflimit}) {
+                last if ++$count >= $opt{perflimit};
+            }
+        }
+        if ($MRTG) {
+            $stats{$db->{dbname}} = $mintime;
+            $statsmsg{$db->{dbname}} = msg('vac-msg', $db->{dbname}, $minrel);
+            return;
+        }
+
+        if ($maxtime == -2) {
+            add_unknown msg('no-match-table');
+        }
+        elsif ($maxtime < 0) {
+            add_unknown $type eq 'vacuum' ? msg('vac-nomatch-v') : msg('vac-nomatch-a');
+        }
+        else {
+            my $showtime = pretty_time($maxtime, 'S');
+            my $msg = "$maxrel: $maxptime ($showtime)";
+            if ($critical and $maxtime >= $critical) {
+                add_critical $msg;
+            }
+            elsif ($warning and $maxtime >= $warning) {
+                add_warning $msg;
+            }
+            else {
+                add_ok $msg;
+            }
+        }
+    }
+
+    return;
 
 } ## end of check_last_vacuum_analyze
 
 
 sub check_listener {
 
-       ## Check for a specific listener
-       ## Supports: Nagios, MRTG
-       ## Critical and warning are simple strings, or regex if starts with a ~
-       ## Example: --critical="~bucardo"
-
-       if ($MRTG and exists $opt{mrtg}) {
-               $opt{critical} = $opt{mrtg};
-       }
-
-       my ($warning, $critical) = validate_range({type => 'restringex', forcemrtg => 1});
-
-       my $string = length $critical ? $critical : $warning;
-       my $regex = ($string =~ s/^~//) ? '~' : '=';
-
-       $SQL = "SELECT count(*) AS c FROM pg_listener WHERE relname $regex '$string'";
-       my $info = run_command($SQL);
-
-       for $db (@{$info->{db}}) {
-               if ($db->{slurp}[0]{c} !~ /(\d+)/) {
-                       add_unknown msg('invalid-query', $db->{slurp});
-                       next;
-               }
-               my $count = $1;
-               if ($MRTG) {
-                       do_mrtg({one => $count});
-               }
-               $db->{perf} .= msg('listener-count', $count);
-               my $msg = msg('listener-msg', $count);
-               if ($count >= 1) {
-                       add_ok $msg;
-               }
-               elsif ($critical) {
-                       add_critical $msg;
-               }
-               else {
-                       add_warning $msg;
-               }
-       }
-       return;
+    ## Check for a specific listener
+    ## Supports: Nagios, MRTG
+    ## Critical and warning are simple strings, or regex if starts with a ~
+    ## Example: --critical="~bucardo"
+
+    if ($MRTG and exists $opt{mrtg}) {
+        $opt{critical} = $opt{mrtg};
+    }
+
+    my ($warning, $critical) = validate_range({type => 'restringex', forcemrtg => 1});
+
+    my $string = length $critical ? $critical : $warning;
+    my $regex = ($string =~ s/^~//) ? '~' : '=';
+
+    $SQL = "SELECT count(*) AS c FROM pg_listener WHERE relname $regex '$string'";
+    my $info = run_command($SQL);
+
+    for $db (@{$info->{db}}) {
+        if ($db->{slurp}[0]{c} !~ /(\d+)/) {
+            add_unknown msg('invalid-query', $db->{slurp});
+            next;
+        }
+        my $count = $1;
+        if ($MRTG) {
+            do_mrtg({one => $count});
+        }
+        $db->{perf} .= msg('listener-count', $count);
+        my $msg = msg('listener-msg', $count);
+        if ($count >= 1) {
+            add_ok $msg;
+        }
+        elsif ($critical) {
+            add_critical $msg;
+        }
+        else {
+            add_warning $msg;
+        }
+    }
+    return;
 
 } ## end of check_listener
 
 
 sub check_locks {
 
-       ## Check the number of locks
-       ## Supports: Nagios, MRTG
-       ## By default, checks all databases
-       ## Can check specific databases with include
-       ## Can ignore databases with exclude
-       ## Warning and critical are either simple numbers, or more complex:
-       ## Use locktype=number;locktype2=number
-       ## The locktype can be "total", "waiting", or the name of a lock
-       ## Lock names are case-insensitive, and do not need the "lock" at the end.
-       ## Example: --warning=100 --critical="total=200;exclusive=20;waiting=5"
-
-       my ($warning, $critical) = validate_range
-               ({
-                 type             => 'multival',
-                 default_warning  => 100,
-                 default_critical => 150,
-                 });
-
-       $SQL = q{SELECT granted, mode, datname FROM pg_locks l JOIN pg_database d ON (d.oid=l.database)};
-       my $info = run_command($SQL, { regex => qr[\s*\w+\s*\|\s*] });
-
-       # Locks are counted globally not by db.
-       # add a limit by db ? (--critical='foodb.total=30 foodb.exclusive=3 postgres.total=3')
-       # end remove the -db option ?
-       # we output for each db, following the specific warning and critical :
-       # time=00.1 foodb.exclusive=2;;3 foodb.total=10;;30 postgres.exclusive=0;;3 postgres.total=1;;3
-       for $db (@{$info->{db}}) {
-               my $gotone = 0;
-               my %dblock;
-               my %totallock = (total => 0);
-         ROW: for my $r (@{$db->{slurp}}) {
-                       my ($granted,$mode,$dbname) = ($r->{granted}, lc $r->{mode}, $r->{datname});
-                       next ROW if skip_item($dbname);
-                       $gotone = 1;
-                       $mode =~ s{lock$}{};
-                       $dblock{$dbname}{total}++;
-                       $dblock{$dbname}{$mode}++;
-                       $dblock{$dbname}{waiting}++ if $granted ne 't';
-               }
-               # Compute total, add hash key for critical and warning specific check
-               for my $k (keys %dblock) {
-                       if ($warning) {
-                               for my $l (keys %{$warning}) {
-                                       $dblock{$k}{$l} = 0 if ! exists $dblock{$k}{$l};
-                               }
-                       }
-                       if ($critical) {
-                               for my $l (keys %{$critical}) {
-                                       $dblock{$k}{$l} = 0 if ! exists $dblock{$k}{$l};
-                               }
-                       }
-                       for my $m (keys %{$dblock{$k}}){
-                               $totallock{$m} += $dblock{$k}{$m};
-                       }
-               }
-
-               if ($MRTG) {
-                       $stats{$db->{dbname}} = $totallock{total};
-                       next;
-               }
-
-               # Nagios perfdata output
-               for my $dbname (sort keys %dblock) {
-                       for my $type (sort keys %{ $dblock{$dbname} }) {
-                               next if ((! $critical or ! exists $critical->{$type})
-                                                        and (!$warning or ! exists $warning->{$type}));
-                               $db->{perf} .= " '$dbname.$type'=$dblock{$dbname}{$type};";
-                               if ($warning and exists $warning->{$type}) {
-                                       $db->{perf} .= $warning->{$type};
-                               }
-                               $db->{perf} .= ';';
-                               if ($critical and $critical->{$type}) {
-                                       $db->{perf} .= $critical->{$type};
-                               }
-                       }
-               }
-
-               if (!$gotone) {
-                       add_unknown msg('no-match-db');
-                       next;
-               }
-
-               ## If not specific errors, just use the total
-               my $ok = 1;
-               for my $type (keys %totallock) {
-                       if ($critical and exists $critical->{$type} and $totallock{$type} >= $critical->{$type}) {
-                               ($type eq 'total')
-                                       ? add_critical msg('locks-msg2', $totallock{total})
-                                       : add_critical msg('locks-msg', $type, $totallock{$type});
-                               $ok = 0;
-                       }
-                       if ($warning and exists $warning->{$type} and $totallock{$type} >= $warning->{$type}) {
-                               ($type eq 'total')
-                               ? add_warning msg('locks-msg2', $totallock{total})
-                               : add_warning msg('locks-msg', $type, $totallock{$type});
-                               $ok = 0;
-                       }
-               }
-               if ($ok) {
-                       my %show;
-                       if (!keys %critical and !keys %warning) {
-                               $show{total} = 1;
-                       }
-                       for my $type (keys %critical) {
-                               $show{$type} = 1;
-                       }
-                       for my $type (keys %warning) {
-                               $show{$type} = 1;
-                       }
-                       my $msg = '';
-                       for (sort keys %show) {
-                               $msg .= sprintf "$_=%d ", $totallock{$_} || 0;
-                       }
-                       add_ok $msg;
-               }
-       }
-
-       return;
+    ## Check the number of locks
+    ## Supports: Nagios, MRTG
+    ## By default, checks all databases
+    ## Can check specific databases with include
+    ## Can ignore databases with exclude
+    ## Warning and critical are either simple numbers, or more complex:
+    ## Use locktype=number;locktype2=number
+    ## The locktype can be "total", "waiting", or the name of a lock
+    ## Lock names are case-insensitive, and do not need the "lock" at the end.
+    ## Example: --warning=100 --critical="total=200;exclusive=20;waiting=5"
+
+    my ($warning, $critical) = validate_range
+        ({
+          type             => 'multival',
+          default_warning  => 100,
+          default_critical => 150,
+          });
+
+    $SQL = q{SELECT granted, mode, datname FROM pg_locks l JOIN pg_database d ON (d.oid=l.database)};
+    my $info = run_command($SQL, { regex => qr[\s*\w+\s*\|\s*] });
+
+    # Locks are counted globally not by db.
+    # add a limit by db ? (--critical='foodb.total=30 foodb.exclusive=3 postgres.total=3')
+    # end remove the -db option ?
+    # we output for each db, following the specific warning and critical :
+    # time=00.1 foodb.exclusive=2;;3 foodb.total=10;;30 postgres.exclusive=0;;3 postgres.total=1;;3
+    for $db (@{$info->{db}}) {
+        my $gotone = 0;
+        my %dblock;
+        my %totallock = (total => 0);
+      ROW: for my $r (@{$db->{slurp}}) {
+            my ($granted,$mode,$dbname) = ($r->{granted}, lc $r->{mode}, $r->{datname});
+            next ROW if skip_item($dbname);
+            $gotone = 1;
+            $mode =~ s{lock$}{};
+            $dblock{$dbname}{total}++;
+            $dblock{$dbname}{$mode}++;
+            $dblock{$dbname}{waiting}++ if $granted ne 't';
+        }
+        # Compute total, add hash key for critical and warning specific check
+        for my $k (keys %dblock) {
+            if ($warning) {
+                for my $l (keys %{$warning}) {
+                    $dblock{$k}{$l} = 0 if ! exists $dblock{$k}{$l};
+                }
+            }
+            if ($critical) {
+                for my $l (keys %{$critical}) {
+                    $dblock{$k}{$l} = 0 if ! exists $dblock{$k}{$l};
+                }
+            }
+            for my $m (keys %{$dblock{$k}}){
+                $totallock{$m} += $dblock{$k}{$m};
+            }
+        }
+
+        if ($MRTG) {
+            $stats{$db->{dbname}} = $totallock{total};
+            next;
+        }
+
+        # Nagios perfdata output
+        for my $dbname (sort keys %dblock) {
+            for my $type (sort keys %{ $dblock{$dbname} }) {
+                next if ((! $critical or ! exists $critical->{$type})
+                             and (!$warning or ! exists $warning->{$type}));
+                $db->{perf} .= " '$dbname.$type'=$dblock{$dbname}{$type};";
+                if ($warning and exists $warning->{$type}) {
+                    $db->{perf} .= $warning->{$type};
+                }
+                $db->{perf} .= ';';
+                if ($critical and $critical->{$type}) {
+                    $db->{perf} .= $critical->{$type};
+                }
+            }
+        }
+
+        if (!$gotone) {
+            add_unknown msg('no-match-db');
+            next;
+        }
+
+        ## If not specific errors, just use the total
+        my $ok = 1;
+        for my $type (keys %totallock) {
+            if ($critical and exists $critical->{$type} and $totallock{$type} >= $critical->{$type}) {
+                ($type eq 'total')
+                    ? add_critical msg('locks-msg2', $totallock{total})
+                    : add_critical msg('locks-msg', $type, $totallock{$type});
+                $ok = 0;
+            }
+            if ($warning and exists $warning->{$type} and $totallock{$type} >= $warning->{$type}) {
+                ($type eq 'total')
+                ? add_warning msg('locks-msg2', $totallock{total})
+                : add_warning msg('locks-msg', $type, $totallock{$type});
+                $ok = 0;
+            }
+        }
+        if ($ok) {
+            my %show;
+            if (!keys %critical and !keys %warning) {
+                $show{total} = 1;
+            }
+            for my $type (keys %critical) {
+                $show{$type} = 1;
+            }
+            for my $type (keys %warning) {
+                $show{$type} = 1;
+            }
+            my $msg = '';
+            for (sort keys %show) {
+                $msg .= sprintf "$_=%d ", $totallock{$_} || 0;
+            }
+            add_ok $msg;
+        }
+    }
+
+    return;
 
 } ## end of check_locks
 
 
 sub check_logfile {
 
-       ## Make sure the logfile is getting written to
-       ## Supports: Nagios, MRTG
-       ## Especially useful for syslog redirectors
-       ## Should be run on the system housing the logs
-       ## Optional argument "logfile" tells where the logfile is
-       ## Allows for some conversion characters.
-       ## Example: --logfile="/syslog/%Y-m%-d%/H%/postgres.log"
-       ## Critical and warning are not used: it's either ok or critical.
+    ## Make sure the logfile is getting written to
+    ## Supports: Nagios, MRTG
+    ## Especially useful for syslog redirectors
+    ## Should be run on the system housing the logs
+    ## Optional argument "logfile" tells where the logfile is
+    ## Allows for some conversion characters.
+    ## Example: --logfile="/syslog/%Y-m%-d%/H%/postgres.log"
+    ## Critical and warning are not used: it's either ok or critical.
 
-       my $critwarn = $opt{warning} ? 0 : 1;
+    my $critwarn = $opt{warning} ? 0 : 1;
 
-       $SQL = q{
+    $SQL = q{
 SELECT name, CASE WHEN length(setting)<1 THEN '?' ELSE setting END AS s
 FROM pg_settings
 WHERE name IN ('log_destination','log_directory','log_filename','redirect_stderr','syslog_facility')
 ORDER BY name
 };
 
-       my $logfilere = qr{^[\w_\s\/%\-\.]+$};
-       if (exists $opt{logfile} and $opt{logfile} !~ $logfilere) {
-               ndie msg('logfile-opt-bad');
-       }
-
-       my $info = run_command($SQL);
-       $VERBOSE >= 3 and warn Dumper $info;
-
-       for $db (@{$info->{db}}) {
-               my $i;
-               for my $r (@{$db->{slurp}}) {
-                       $i->{$r->{name}} = $r->{s} || '?';
-               }
-               for my $word (qw{ log_destination log_directory log_filename redirect_stderr syslog_facility }) {
-                       $i->{$word} = '?' if ! exists $i->{$word};
-               }
-
-               ## Figure out what we think the log file will be
-               my $logfile ='';
-               if (exists $opt{logfile} and $opt{logfile} =~ /\w/) {
-                       $logfile = $opt{logfile};
-               }
-               else {
-                       if ($i->{log_destination} eq 'syslog') {
-                               ## We'll make a best effort to figure out where it is. Using the --logfile option is preferred.
-                               $logfile = '/var/log/messages';
-                               if (open my $cfh, '<', '/etc/syslog.conf') {
-                                       while (<$cfh>) {
-                                               if (/\b$i->{syslog_facility}\.(?!none).+?([\w\/]+)$/i) {
-                                                       $logfile = $1;
-                                               }
-                                       }
-                               }
-                               if (!$logfile or ! -e $logfile) {
-                                       ndie msg('logfile-syslog', $i->{syslog_facility});
-                               }
-                       }
-                       elsif ($i->{log_destination} eq 'stderr') {
-                               if ($i->{redirect_stderr} ne 'yes') {
-                                       ndie msg('logfile-stderr');
-                               }
-                       }
-               }
-
-               ## We now have a logfile (or a template)..parse it into pieces.
-               ## We need at least hour, day, month, year
-               my @t = localtime;
-               my ($H,$d,$m,$Y) = (sprintf ('%02d',$t[2]),sprintf('%02d',$t[3]),sprintf('%02d',$t[4]+1),$t[5]+1900);
-               if ($logfile !~ $logfilere) {
-                       ndie msg('logfile-bad',$logfile);
-               }
-               $logfile =~ s/%%/~~/g;
-               $logfile =~ s/%Y/$Y/g;
-               $logfile =~ s/%m/$m/g;
-               $logfile =~ s/%d/$d/g;
-               $logfile =~ s/%H/$H/g;
-
-               $VERBOSE >= 3 and warn msg('logfile-debug2', $logfile);
-
-               if (! -e $logfile) {
-                       my $msg = msg('logfile-dne', $logfile);
-                       $MRTG and ndie $msg;
-                       if ($critwarn) {
-                               add_unknown $msg;
-                       }
-                       else {
-                               add_warning $msg;
-                       }
-                       next;
-               }
-               my $logfh;
-               unless (open $logfh, '<', $logfile) {
-                       add_unknown msg('logfile-openfail', $logfile, $!);
-                       next;
-               }
-               seek($logfh, 0, 2) or ndie msg('logfile-seekfail', $logfile, $!);
-
-               ## Throw a custom error string.
-               ## We do the number first as old versions only show part of the string.
-               my $random_number = int rand(999999999999);
-               my $funky = sprintf "check_postgres_logfile_error_$random_number $ME DB=$db->{dbname} PID=$$ Time=%s",
-                       scalar localtime;
-
-               ## Cause an error on just this target
-               delete @{$db}{qw(ok slurp totaltime)};
-               my $badinfo = run_command("$funky", {failok => 1, target => $db} );
-
-               my $MAXSLEEPTIME = $opt{timeout} || 20;
-               my $SLEEP = 1;
-               my $found = 0;
-               LOGWAIT: {
-                       sleep $SLEEP;
-                       seek $logfh, 0, 1 or ndie msg('logfile-seekfail', $logfile, $!);
-                       while (<$logfh>) {
-                               if (/logfile_error_$random_number/) { ## Some logs break things up, so we don't use funky
-                                       $found = 1;
-                                       last LOGWAIT;
-                               }
-                       }
-                       $MAXSLEEPTIME -= $SLEEP;
-                       redo if $MAXSLEEPTIME > 0;
-                       my $msg = msg('logfile-fail', $logfile);
-                       $MRTG and do_mrtg({one => 0, msg => $msg});
-                       if ($critwarn) {
-                               add_critical $msg;
-                       }
-                       else {
-                               add_warning $msg;
-                       }
-               }
-               close $logfh or ndie msg('file-noclose', $logfile, $!);
-
-               if ($found == 1) {
-                       $MRTG and do_mrtg({one => 1});
-                       add_ok msg('logfile-ok', $logfile);
-               }
-       }
-       return;
+    my $logfilere = qr{^[\w_\s\/%\-\.]+$};
+    if (exists $opt{logfile} and $opt{logfile} !~ $logfilere) {
+        ndie msg('logfile-opt-bad');
+    }
+
+    my $info = run_command($SQL);
+    $VERBOSE >= 3 and warn Dumper $info;
+
+    for $db (@{$info->{db}}) {
+        my $i;
+        for my $r (@{$db->{slurp}}) {
+            $i->{$r->{name}} = $r->{s} || '?';
+        }
+        for my $word (qw{ log_destination log_directory log_filename redirect_stderr syslog_facility }) {
+            $i->{$word} = '?' if ! exists $i->{$word};
+        }
+
+        ## Figure out what we think the log file will be
+        my $logfile ='';
+        if (exists $opt{logfile} and $opt{logfile} =~ /\w/) {
+            $logfile = $opt{logfile};
+        }
+        else {
+            if ($i->{log_destination} eq 'syslog') {
+                ## We'll make a best effort to figure out where it is. Using the --logfile option is preferred.
+                $logfile = '/var/log/messages';
+                if (open my $cfh, '<', '/etc/syslog.conf') {
+                    while (<$cfh>) {
+                        if (/\b$i->{syslog_facility}\.(?!none).+?([\w\/]+)$/i) {
+                            $logfile = $1;
+                        }
+                    }
+                }
+                if (!$logfile or ! -e $logfile) {
+                    ndie msg('logfile-syslog', $i->{syslog_facility});
+                }
+            }
+            elsif ($i->{log_destination} eq 'stderr') {
+                if ($i->{redirect_stderr} ne 'yes') {
+                    ndie msg('logfile-stderr');
+                }
+            }
+        }
+
+        ## We now have a logfile (or a template)..parse it into pieces.
+        ## We need at least hour, day, month, year
+        my @t = localtime;
+        my ($H,$d,$m,$Y) = (sprintf ('%02d',$t[2]),sprintf('%02d',$t[3]),sprintf('%02d',$t[4]+1),$t[5]+1900);
+        if ($logfile !~ $logfilere) {
+            ndie msg('logfile-bad',$logfile);
+        }
+        $logfile =~ s/%%/~~/g;
+        $logfile =~ s/%Y/$Y/g;
+        $logfile =~ s/%m/$m/g;
+        $logfile =~ s/%d/$d/g;
+        $logfile =~ s/%H/$H/g;
+
+        $VERBOSE >= 3 and warn msg('logfile-debug2', $logfile);
+
+        if (! -e $logfile) {
+            my $msg = msg('logfile-dne', $logfile);
+            $MRTG and ndie $msg;
+            if ($critwarn) {
+                add_unknown $msg;
+            }
+            else {
+                add_warning $msg;
+            }
+            next;
+        }
+        my $logfh;
+        unless (open $logfh, '<', $logfile) {
+            add_unknown msg('logfile-openfail', $logfile, $!);
+            next;
+        }
+        seek($logfh, 0, 2) or ndie msg('logfile-seekfail', $logfile, $!);
+
+        ## Throw a custom error string.
+        ## We do the number first as old versions only show part of the string.
+        my $random_number = int rand(999999999999);
+        my $funky = sprintf "check_postgres_logfile_error_$random_number $ME DB=$db->{dbname} PID=$$ Time=%s",
+            scalar localtime;
+
+        ## Cause an error on just this target
+        delete @{$db}{qw(ok slurp totaltime)};
+        my $badinfo = run_command("$funky", {failok => 1, target => $db} );
+
+        my $MAXSLEEPTIME = $opt{timeout} || 20;
+        my $SLEEP = 1;
+        my $found = 0;
+        LOGWAIT: {
+            sleep $SLEEP;
+            seek $logfh, 0, 1 or ndie msg('logfile-seekfail', $logfile, $!);
+            while (<$logfh>) {
+                if (/logfile_error_$random_number/) { ## Some logs break things up, so we don't use funky
+                    $found = 1;
+                    last LOGWAIT;
+                }
+            }
+            $MAXSLEEPTIME -= $SLEEP;
+            redo if $MAXSLEEPTIME > 0;
+            my $msg = msg('logfile-fail', $logfile);
+            $MRTG and do_mrtg({one => 0, msg => $msg});
+            if ($critwarn) {
+                add_critical $msg;
+            }
+            else {
+                add_warning $msg;
+            }
+        }
+        close $logfh or ndie msg('file-noclose', $logfile, $!);
+
+        if ($found == 1) {
+            $MRTG and do_mrtg({one => 1});
+            add_ok msg('logfile-ok', $logfile);
+        }
+    }
+    return;
 
 } ## end of check_logfile
 
 
 sub check_new_version_bc {
 
-       ## Check if a new version of Bucardo is available
-
-       my $site = 'bucardo.org';
-       my $path = 'bucardo/latest_version.txt';
-       my $url = "http://$site/$path";
-       my ($newver,$maj,$rev,$message) = ('','','','');
-       my $versionre = qr{((\d+\.\d+)\.(\d+))\s+(.+)};
-
-       for my $meth (@get_methods) {
-               eval {
-                       my $COM = "$meth $url";
-                       $VERBOSE >= 1 and warn "TRYING: $COM\n";
-                       my $info = qx{$COM 2>/dev/null};
-                       if ($info =~ $versionre) {
-                               ($newver,$maj,$rev,$message) = ($1,$2,$3,$4);
-                       }
-                       $VERBOSE >=1 and warn "SET version to $newver\n";
-               };
-               last if length $newver;
-       }
-
-       if (! length $newver) {
-               add_unknown msg('new-bc-fail');
-               return;
-       }
-
-       my $BCVERSION = '?';
-       eval {
-               $BCVERSION = qx{bucardo_ctl --version 2>&1};
-       };
-       if ($@ or !$BCVERSION) {
-               add_unknown msg('new-bc-badver');
-               return;
-       }
-
-       if ($BCVERSION !~ s/.*((\d+\.\d+)\.(\d+)).*/$1/s) {
-               add_unknown msg('new-bc-fail');
-               return;
-       }
-       my ($cmaj,$crev) = ($2,$3);
-
-       if ($newver eq $BCVERSION) {
-               add_ok msg('new-bc-ok', $newver);
-               return;
-       }
-
-       $nohost = $message;
-       if ($cmaj eq $maj) {
-               add_critical msg('new-bc-warn', $newver, $BCVERSION);
-       }
-       else {
-               add_warning msg('new-bc-warn', $newver, $BCVERSION);
-       }
-       return;
+    ## Check if a new version of Bucardo is available
+
+    my $site = 'bucardo.org';
+    my $path = 'bucardo/latest_version.txt';
+    my $url = "http://$site/$path";
+    my ($newver,$maj,$rev,$message) = ('','','','');
+    my $versionre = qr{((\d+\.\d+)\.(\d+))\s+(.+)};
+
+    for my $meth (@get_methods) {
+        eval {
+            my $COM = "$meth $url";
+            $VERBOSE >= 1 and warn "TRYING: $COM\n";
+            my $info = qx{$COM 2>/dev/null};
+            if ($info =~ $versionre) {
+                ($newver,$maj,$rev,$message) = ($1,$2,$3,$4);
+            }
+            $VERBOSE >=1 and warn "SET version to $newver\n";
+        };
+        last if length $newver;
+    }
+
+    if (! length $newver) {
+        add_unknown msg('new-bc-fail');
+        return;
+    }
+
+    my $BCVERSION = '?';
+    eval {
+        $BCVERSION = qx{bucardo_ctl --version 2>&1};
+    };
+    if ($@ or !$BCVERSION) {
+        add_unknown msg('new-bc-badver');
+        return;
+    }
+
+    if ($BCVERSION !~ s/.*((\d+\.\d+)\.(\d+)).*/$1/s) {
+        add_unknown msg('new-bc-fail');
+        return;
+    }
+    my ($cmaj,$crev) = ($2,$3);
+
+    if ($newver eq $BCVERSION) {
+        add_ok msg('new-bc-ok', $newver);
+        return;
+    }
+
+    $nohost = $message;
+    if ($cmaj eq $maj) {
+        add_critical msg('new-bc-warn', $newver, $BCVERSION);
+    }
+    else {
+        add_warning msg('new-bc-warn', $newver, $BCVERSION);
+    }
+    return;
 
 } ## end of check_new_version_bc
 
 
 sub check_new_version_cp {
 
-       ## Check if a new version of check_postgres.pl is available
-       ## You probably don't want to run this one every five minutes. :)
-
-       my $site = 'bucardo.org';
-       my $path = 'check_postgres/latest_version.txt';
-       my $url = "http://$site/$path";
-       my ($newver,$maj,$rev,$message) = ('','','','');
-       my $versionre = qr{((\d+\.\d+)\.(\d+))\s+(.+)};
-
-       for my $meth (@get_methods) {
-               eval {
-                       my $COM = "$meth $url";
-                       $VERBOSE >= 1 and warn "TRYING: $COM\n";
-                       my $info = qx{$COM 2>/dev/null};
-                       if ($info =~ $versionre) {
-                               ($newver,$maj,$rev,$message) = ($1,$2,$3,$4);
-                       }
-                       $VERBOSE >=1 and warn "SET version to $newver\n";
-               };
-               last if length $newver;
-       }
-
-       if (! length $newver) {
-               add_unknown msg('new-cp-fail');
-               return;
-       }
-
-       if ($newver eq $VERSION) {
-               add_ok msg('new-cp-ok', $newver);
-               return;
-       }
-
-       if ($VERSION !~ /(\d+\.\d+)\.(\d+)/) {
-               add_unknown msg('new-cp-fail');
-               return;
-       }
-
-       $nohost = $message;
-       my ($cmaj,$crev) = ($1,$2);
-       if ($cmaj eq $maj) {
-               add_warning msg('new-cp-warn', $newver, $VERSION);
-       }
-       else {
-               add_critical msg('new-cp-warn', $newver, $VERSION);
-       }
-       return;
+    ## Check if a new version of check_postgres.pl is available
+    ## You probably don't want to run this one every five minutes. :)
+
+    my $site = 'bucardo.org';
+    my $path = 'check_postgres/latest_version.txt';
+    my $url = "http://$site/$path";
+    my ($newver,$maj,$rev,$message) = ('','','','');
+    my $versionre = qr{((\d+\.\d+)\.(\d+))\s+(.+)};
+
+    for my $meth (@get_methods) {
+        eval {
+            my $COM = "$meth $url";
+            $VERBOSE >= 1 and warn "TRYING: $COM\n";
+            my $info = qx{$COM 2>/dev/null};
+            if ($info =~ $versionre) {
+                ($newver,$maj,$rev,$message) = ($1,$2,$3,$4);
+            }
+            $VERBOSE >=1 and warn "SET version to $newver\n";
+        };
+        last if length $newver;
+    }
+
+    if (! length $newver) {
+        add_unknown msg('new-cp-fail');
+        return;
+    }
+
+    if ($newver eq $VERSION) {
+        add_ok msg('new-cp-ok', $newver);
+        return;
+    }
+
+    if ($VERSION !~ /(\d+\.\d+)\.(\d+)/) {
+        add_unknown msg('new-cp-fail');
+        return;
+    }
+
+    $nohost = $message;
+    my ($cmaj,$crev) = ($1,$2);
+    if ($cmaj eq $maj) {
+        add_warning msg('new-cp-warn', $newver, $VERSION);
+    }
+    else {
+        add_critical msg('new-cp-warn', $newver, $VERSION);
+    }
+    return;
 
 } ## end of check_new_version_cp
 
 
 sub check_new_version_pg {
 
-       ## Check if a new version of Postgres is available
-       ## Note that we only check the revision
-       ## This also depends highly on the web page at postgresql.org not changing format
-
-       my $url = 'http://www.postgresql.org/versions.rss';
-       my $versionre = qr{<title>(\d+)\.(\d+)\.(\d+)</title>};
-
-       my %newver;
-       for my $meth (@get_methods) {
-               eval {
-                       my $COM = "$meth $url";
-                       $VERBOSE >= 1 and warn "TRYING: $COM\n";
-                       my $info = qx{$COM 2>/dev/null};
-                       while ($info =~ /$versionre/g) {
-                               my ($maj,$min,$rev) = ($1,$2,$3);
-                               $newver{"$maj.$min"} = $rev;
-                       }
-               };
-               last if %newver;
-       }
-
-       my $info = run_command('SELECT version() AS version');
-
-       $db = $info->{db}[0];
-
-       if ($db->{slurp}[0]{version} !~ /PostgreSQL (\S+)/o) { ## no critic (ProhibitUnusedCapture)
-               add_unknown msg('invalid-query', $db->{slurp});
-               return;
-       }
-
-       my $currver = $1;
-       if ($currver !~ /(\d+\.\d+)\.(\d+)/) {
-               add_unknown msg('new-pg-badver', $currver);
-               return;
-       }
-
-       my ($ver,$rev) = ($1,$2);
-       if (! exists $newver{$ver}) {
-               add_unknown msg('new-pg-badver2', $ver);
-               return;
-       }
-
-       my $newrev = $newver{$ver};
-       if ($newrev > $rev) {
-               add_warning msg('new-pg-big', "$ver.$newrev", $currver);
-       }
-       elsif ($newrev < $rev) {
-               add_critical msg('new-pg-small', "$ver.$newrev", $currver);
-       }
-       else {
-               add_ok msg('new-pg-match', $currver);
-       }
-
-       return;
+    ## Check if a new version of Postgres is available
+    ## Note that we only check the revision
+    ## This also depends highly on the web page at postgresql.org not changing format
+
+    my $url = 'http://www.postgresql.org/versions.rss';
+    my $versionre = qr{<title>(\d+)\.(\d+)\.(\d+)</title>};
+
+    my %newver;
+    for my $meth (@get_methods) {
+        eval {
+            my $COM = "$meth $url";
+            $VERBOSE >= 1 and warn "TRYING: $COM\n";
+            my $info = qx{$COM 2>/dev/null};
+            while ($info =~ /$versionre/g) {
+                my ($maj,$min,$rev) = ($1,$2,$3);
+                $newver{"$maj.$min"} = $rev;
+            }
+        };
+        last if %newver;
+    }
+
+    my $info = run_command('SELECT version() AS version');
+
+    $db = $info->{db}[0];
+
+    if ($db->{slurp}[0]{version} !~ /PostgreSQL (\S+)/o) { ## no critic (ProhibitUnusedCapture)
+        add_unknown msg('invalid-query', $db->{slurp});
+        return;
+    }
+
+    my $currver = $1;
+    if ($currver !~ /(\d+\.\d+)\.(\d+)/) {
+        add_unknown msg('new-pg-badver', $currver);
+        return;
+    }
+
+    my ($ver,$rev) = ($1,$2);
+    if (! exists $newver{$ver}) {
+        add_unknown msg('new-pg-badver2', $ver);
+        return;
+    }
+
+    my $newrev = $newver{$ver};
+    if ($newrev > $rev) {
+        add_warning msg('new-pg-big', "$ver.$newrev", $currver);
+    }
+    elsif ($newrev < $rev) {
+        add_critical msg('new-pg-small', "$ver.$newrev", $currver);
+    }
+    else {
+        add_ok msg('new-pg-match', $currver);
+    }
+
+    return;
 
 } ## end of check_new_version_pg
 
 
 sub check_pg_stat_activity {
 
-       ## Common function to run various actions against the pg_stat_activity view
-       ## Actions: txn_idle, txn_time, query_time
-       ## Supports: Nagios, MRTG
-       ## It makes no sense to run this more than once on the same cluster
-       ## Warning and critical are time limits - defaults to seconds
-       ## Valid units: s[econd], m[inute], h[our], d[ay]
-       ## All above may be written as plural as well (e.g. "2 hours")
-       ## Can also ignore databases with exclude and limit with include
-       ## Limit to a specific user with the includeuser option
-       ## Exclude users with the excludeuser option
-
-       my $arg = shift || {};
-
-       my ($warning, $critical) = validate_range
-               ({
-                 type             => 'time',
-                 default_warning  => $arg->{default_warning},
-                 default_critical => $arg->{default_critical},
-                 });
-
-       ## Grab information from the pg_stat_activity table
-       ## Since we clobber old info on a qtime "tie", use an ORDER BY
-       $SQL = qq{
+    ## Common function to run various actions against the pg_stat_activity view
+    ## Actions: txn_idle, txn_time, query_time
+    ## Supports: Nagios, MRTG
+    ## It makes no sense to run this more than once on the same cluster
+    ## Warning and critical are time limits - defaults to seconds
+    ## Valid units: s[econd], m[inute], h[our], d[ay]
+    ## All above may be written as plural as well (e.g. "2 hours")
+    ## Can also ignore databases with exclude and limit with include
+    ## Limit to a specific user with the includeuser option
+    ## Exclude users with the excludeuser option
+
+    my $arg = shift || {};
+
+    my ($warning, $critical) = validate_range
+        ({
+          type             => 'time',
+          default_warning  => $arg->{default_warning},
+          default_critical => $arg->{default_critical},
+          });
+
+    ## Grab information from the pg_stat_activity table
+    ## Since we clobber old info on a qtime "tie", use an ORDER BY
+    $SQL = qq{
 SELECT
  xact_start,
  SUBSTR(current_query,0,100) AS current_query,
@@ -4299,664 +4299,664 @@ WHERE $arg->{whereclause} $USERWHERECLAUSE
 ORDER BY xact_start, procpid DESC
 };
 
-       my $info = run_command($SQL, { regex => qr{\d+}, emptyok => 1 } );
-
-       ## Default values for information gathered
-       my ($maxact, $maxtime, $client_addr, $client_port, $procpid, $username, $maxdb, $maxq) =
-               ('?',0,'?','?','?','?','?','?');
-
-       for $db (@{$info->{db}}) {
-
-               ## Parse the psql output and gather stats from the winning row
-               ## Read in and parse the psql output
-               my $skipped = 0;
-         ROW: for my $r (@{$db->{slurp}}) {
-
-                       ## Apply --exclude and --include arguments to the database name
-                       if (skip_item($r->{datname})) {
-                               $skipped++;
-                               next ROW;
-                       }
-
-                       ## Detect cases where pg_stat_activity is not fully populated
-                       if ($r->{xact_start} !~ /\d/o) {
-                               ## Perhaps this is a non-superuser?
-                               if ($r->{current_query} =~ /insufficient/) {
-                                       add_unknown msg('psa-nosuper');
-                               }
-                               ## Perhaps stats_command_string / track_activities is off?
-                               elsif ($r->{current_query} =~ /disabled/) {
-                                       add_unknown msg('psa-disabled');
-                               }
-                               ## Something else is going on
-                               else {
-                                       add_unknown msg('psa-noxact');
-                               }
-                               return;
-                       }
-
-                       ## Assign stats if we have a new winner
-                       if ($r->{qtime} >= $maxtime) {
-                               $maxact      = $r->{xact_start};
-                               $client_addr = $r->{client_addr};
-                               $client_port = $r->{client_port};
-                               $procpid     = $r->{procpid};
-                               $maxtime     = $r->{qtime};
-                               $maxdb       = $r->{datname};
-                               $username    = $r->{usename};
-                               $maxq        = $r->{current_query};
-                       }
-               }
-
-               ## We don't really care why things matches as far as the final output
-               ## But it's nice to report what we can
-               if ($maxdb eq '?') {
-                       $MRTG and do_mrtg({one => 0, msg => 'No rows'});
-                       $db->{perf} = "0;$warning;$critical";
-
-                       if ($skipped) {
-                               add_ok msg('psa-skipped', $skipped);
-                       }
-                       else {
-                               add_ok msg('psa-nomatches');
-                       }
-                       return;
-               }
-
-               ## Details on who the offender was
-               my $whodunit = sprintf q{%s:%s %s:%s%s%s %s:%s},
-                       msg('database'),
-                       $maxdb,
-                       msg('PID'),
-                       $procpid,
-                       $client_port < 1 ? '' : (sprintf ' %s:%s', msg('port'), $client_port),
-                       $client_addr eq '' ? '' : (sprintf ' %s:%s', msg('address'), $client_addr),
-                       msg('username'),
-                       $username;
-
-               my $details = '';
-               if ($VERBOSE >= 1 and $maxtime > 0) { ## >0 so we don't report ourselves
-                       $maxq =~ s/\n/\\n/g;
-                       $details = " " . msg('Query', $maxq);
-               }
-
-               $MRTG and do_mrtg({one => $maxtime, msg => "$whodunit$details"});
-
-               $db->{perf} .= sprintf q{'%s'=%s;%s;%s},
-                       $whodunit,
-                       $maxtime,
-                       $warning,
-                       $critical;
-
-               my $m = $action eq 'query_time' ? msg('qtime-msg', $maxtime)
-                       : $action eq 'txn_time'   ? msg('txntime-msg', $maxtime)
-                       : $action eq 'txn_idle'   ? msg('txnidle-msg', $maxtime)
-                       : die "Unkown action: $action\n";
-               my $msg = sprintf '%s (%s)%s', $m, $whodunit, $details;
-
-               if (length $critical and $maxtime >= $critical) {
-                       add_critical $msg;
-               }
-               elsif (length $warning and $maxtime >= $warning) {
-                       add_warning $msg;
-               }
-               else {
-                       add_ok $msg;
-               }
-       }
-
-       return;
+    my $info = run_command($SQL, { regex => qr{\d+}, emptyok => 1 } );
+
+    ## Default values for information gathered
+    my ($maxact, $maxtime, $client_addr, $client_port, $procpid, $username, $maxdb, $maxq) =
+        ('?',0,'?','?','?','?','?','?');
+
+    for $db (@{$info->{db}}) {
+
+        ## Parse the psql output and gather stats from the winning row
+        ## Read in and parse the psql output
+        my $skipped = 0;
+      ROW: for my $r (@{$db->{slurp}}) {
+
+            ## Apply --exclude and --include arguments to the database name
+            if (skip_item($r->{datname})) {
+                $skipped++;
+                next ROW;
+            }
+
+            ## Detect cases where pg_stat_activity is not fully populated
+            if ($r->{xact_start} !~ /\d/o) {
+                ## Perhaps this is a non-superuser?
+                if ($r->{current_query} =~ /insufficient/) {
+                    add_unknown msg('psa-nosuper');
+                }
+                ## Perhaps stats_command_string / track_activities is off?
+                elsif ($r->{current_query} =~ /disabled/) {
+                    add_unknown msg('psa-disabled');
+                }
+                ## Something else is going on
+                else {
+                    add_unknown msg('psa-noxact');
+                }
+                return;
+            }
+
+            ## Assign stats if we have a new winner
+            if ($r->{qtime} >= $maxtime) {
+                $maxact      = $r->{xact_start};
+                $client_addr = $r->{client_addr};
+                $client_port = $r->{client_port};
+                $procpid     = $r->{procpid};
+                $maxtime     = $r->{qtime};
+                $maxdb       = $r->{datname};
+                $username    = $r->{usename};
+                $maxq        = $r->{current_query};
+            }
+        }
+
+        ## We don't really care why things matches as far as the final output
+        ## But it's nice to report what we can
+        if ($maxdb eq '?') {
+            $MRTG and do_mrtg({one => 0, msg => 'No rows'});
+            $db->{perf} = "0;$warning;$critical";
+
+            if ($skipped) {
+                add_ok msg('psa-skipped', $skipped);
+            }
+            else {
+                add_ok msg('psa-nomatches');
+            }
+            return;
+        }
+
+        ## Details on who the offender was
+        my $whodunit = sprintf q{%s:%s %s:%s%s%s %s:%s},
+            msg('database'),
+            $maxdb,
+            msg('PID'),
+            $procpid,
+            $client_port < 1 ? '' : (sprintf ' %s:%s', msg('port'), $client_port),
+            $client_addr eq '' ? '' : (sprintf ' %s:%s', msg('address'), $client_addr),
+            msg('username'),
+            $username;
+
+        my $details = '';
+        if ($VERBOSE >= 1 and $maxtime > 0) { ## >0 so we don't report ourselves
+            $maxq =~ s/\n/\\n/g;
+            $details = " " . msg('Query', $maxq);
+        }
+
+        $MRTG and do_mrtg({one => $maxtime, msg => "$whodunit$details"});
+
+        $db->{perf} .= sprintf q{'%s'=%s;%s;%s},
+            $whodunit,
+            $maxtime,
+            $warning,
+            $critical;
+
+        my $m = $action eq 'query_time' ? msg('qtime-msg', $maxtime)
+            : $action eq 'txn_time'   ? msg('txntime-msg', $maxtime)
+              : $action eq 'txn_idle'   ? msg('txnidle-msg', $maxtime)
+              : die "Unkown action: $action\n";
+        my $msg = sprintf '%s (%s)%s', $m, $whodunit, $details;
+
+        if (length $critical and $maxtime >= $critical) {
+            add_critical $msg;
+        }
+        elsif (length $warning and $maxtime >= $warning) {
+            add_warning $msg;
+        }
+        else {
+            add_ok $msg;
+        }
+    }
+
+    return;
 
 } ## end of check_pg_stat_activity
 
 
 sub check_pgbouncer_checksum {
 
-       ## Verify the checksum of all pgbouncer settings
-       ## Supports: Nagios, MRTG
-       ## Not that the connection will be done on the pgbouncer database
-       ## One of warning or critical must be given (but not both)
-       ## It should run one time to find out the expected checksum
-       ## You can use --critical="0" to find out the checksum
-       ## You can include or exclude settings as well
-       ## Example:
-       ##  check_postgres_pgbouncer_checksum --critical="4e7ba68eb88915d3d1a36b2009da4acd"
-
-       my ($warning, $critical) = validate_range({type => 'checksum', onlyone => 1});
-
-       eval {
-               require Digest::MD5;
-       };
-       if ($@) {
-               ndie msg('checksum-nomd');
-       }
-
-       $SQL = 'SHOW CONFIG';
-       my $info = run_command($SQL, { regex => qr[log_pooler_errors] });
-
-       $db = $info->{db};
-
-       my $newstring = '';
-       for my $r (@{$db->{slurp}}) {
-               my $key = $r->{key};
-               next if skip_item($key);
-               $newstring .= "$r->{key} = $r->{value}\n";
-       }
-
-       if (! length $newstring) {
-               add_unknown msg('no-match-set');
-       }
-
-       my $checksum = Digest::MD5::md5_hex($newstring);
-
-       my $msg = msg('checksum-msg', $checksum);
-       if ($MRTG) {
-               $opt{mrtg} or ndie msg('checksum-nomrtg');
-               do_mrtg({one => $opt{mrtg} eq $checksum ? 1 : 0, msg => $checksum});
-       }
-       if ($critical and $critical ne $checksum) {
-               add_critical $msg;
-       }
-       elsif ($warning and $warning ne $checksum) {
-               add_warning $msg;
-       }
-       elsif (!$critical and !$warning) {
-               add_unknown $msg;
-       }
-       else {
-               add_ok $msg;
-       }
-
-       return;
+    ## Verify the checksum of all pgbouncer settings
+    ## Supports: Nagios, MRTG
+    ## Not that the connection will be done on the pgbouncer database
+    ## One of warning or critical must be given (but not both)
+    ## It should run one time to find out the expected checksum
+    ## You can use --critical="0" to find out the checksum
+    ## You can include or exclude settings as well
+    ## Example:
+    ##  check_postgres_pgbouncer_checksum --critical="4e7ba68eb88915d3d1a36b2009da4acd"
+
+    my ($warning, $critical) = validate_range({type => 'checksum', onlyone => 1});
+
+    eval {
+        require Digest::MD5;
+    };
+    if ($@) {
+        ndie msg('checksum-nomd');
+    }
+
+    $SQL = 'SHOW CONFIG';
+    my $info = run_command($SQL, { regex => qr[log_pooler_errors] });
+
+    $db = $info->{db};
+
+    my $newstring = '';
+    for my $r (@{$db->{slurp}}) {
+        my $key = $r->{key};
+        next if skip_item($key);
+        $newstring .= "$r->{key} = $r->{value}\n";
+    }
+
+    if (! length $newstring) {
+        add_unknown msg('no-match-set');
+    }
+
+    my $checksum = Digest::MD5::md5_hex($newstring);
+
+    my $msg = msg('checksum-msg', $checksum);
+    if ($MRTG) {
+        $opt{mrtg} or ndie msg('checksum-nomrtg');
+        do_mrtg({one => $opt{mrtg} eq $checksum ? 1 : 0, msg => $checksum});
+    }
+    if ($critical and $critical ne $checksum) {
+        add_critical $msg;
+    }
+    elsif ($warning and $warning ne $checksum) {
+        add_warning $msg;
+    }
+    elsif (!$critical and !$warning) {
+        add_unknown $msg;
+    }
+    else {
+        add_ok $msg;
+    }
+
+    return;
 
 } ## end of check_pgbouncer_checksum
 
 
 sub check_prepared_txns {
 
-       ## Checks age of prepared transactions
-       ## Most installations probably want no prepared_transactions
-       ## Supports: Nagios, MRTG
+    ## Checks age of prepared transactions
+    ## Most installations probably want no prepared_transactions
+    ## Supports: Nagios, MRTG
 
-       my ($warning, $critical) = validate_range
-               ({
-                 type              => 'seconds',
-                 default_warning   => '1',
-                 default_critical  => '30',
-               });
+    my ($warning, $critical) = validate_range
+        ({
+          type              => 'seconds',
+          default_warning   => '1',
+          default_critical  => '30',
+        });
 
-       my $SQL = q{
+    my $SQL = q{
 SELECT database, ROUND(EXTRACT(epoch FROM now()-prepared)) AS age, prepared
 FROM pg_prepared_xacts
 ORDER BY prepared ASC
 };
 
-       my $info = run_command($SQL, {regex => qr[\w+], emptyok => 1 } );
-
-       my $msg = msg('preptxn-none');
-       my $found = 0;
-       for $db (@{$info->{db}}) {
-               my (@crit,@warn,@ok);
-               my ($maxage,$maxdb) = (0,''); ## used by MRTG only
-         ROW: for my $r (@{$db->{slurp}}) {
-                       my ($dbname,$age,$date) = ($r->{database},$r->{age},$r->{prepared});
-                       $found = 1 if ! $found;
-                       next ROW if skip_item($dbname);
-                       $found = 2;
-                       if ($MRTG) {
-                               if ($age > $maxage) {
-                                       $maxdb = $dbname;
-                                       $maxage = $age;
-                               }
-                               elsif ($age == $maxage) {
-                                       $maxdb .= sprintf "%s$dbname", length $maxdb ? ' | ' : '';
-                               }
-                               next;
-                       }
-
-                       $msg = "$dbname=$date ($age)";
-                       $db->{perf} .= " $msg";
-                       if (length $critical and $age >= $critical) {
-                               push @crit => $msg;
-                       }
-                       elsif (length $warning and $age >= $warning) {
-                               push @warn => $msg;
-                       }
-                       else {
-                               push @ok => $msg;
-                       }
-               }
-               if ($MRTG) {
-                       do_mrtg({one => $maxage, msg => $maxdb});
-               }
-               elsif (0 == $found) {
-                       add_ok msg('preptxn-none');
-               }
-               elsif (1 == $found) {
-                       add_unknown msg('no-match-db');
-               }
-               elsif (@crit) {
-                       add_critical join ' ' => @crit;
-               }
-               elsif (@warn) {
-                       add_warning join ' ' => @warn;
-               }
-               else {
-                       add_ok join ' ' => @ok;
-               }
-       }
-
-       return;
+    my $info = run_command($SQL, {regex => qr[\w+], emptyok => 1 } );
+
+    my $msg = msg('preptxn-none');
+    my $found = 0;
+    for $db (@{$info->{db}}) {
+        my (@crit,@warn,@ok);
+        my ($maxage,$maxdb) = (0,''); ## used by MRTG only
+      ROW: for my $r (@{$db->{slurp}}) {
+            my ($dbname,$age,$date) = ($r->{database},$r->{age},$r->{prepared});
+            $found = 1 if ! $found;
+            next ROW if skip_item($dbname);
+            $found = 2;
+            if ($MRTG) {
+                if ($age > $maxage) {
+                    $maxdb = $dbname;
+                    $maxage = $age;
+                }
+                elsif ($age == $maxage) {
+                    $maxdb .= sprintf "%s$dbname", length $maxdb ? ' | ' : '';
+                }
+                next;
+            }
+
+            $msg = "$dbname=$date ($age)";
+            $db->{perf} .= " $msg";
+            if (length $critical and $age >= $critical) {
+                push @crit => $msg;
+            }
+            elsif (length $warning and $age >= $warning) {
+                push @warn => $msg;
+            }
+            else {
+                push @ok => $msg;
+            }
+        }
+        if ($MRTG) {
+            do_mrtg({one => $maxage, msg => $maxdb});
+        }
+        elsif (0 == $found) {
+            add_ok msg('preptxn-none');
+        }
+        elsif (1 == $found) {
+            add_unknown msg('no-match-db');
+        }
+        elsif (@crit) {
+            add_critical join ' ' => @crit;
+        }
+        elsif (@warn) {
+            add_warning join ' ' => @warn;
+        }
+        else {
+            add_ok join ' ' => @ok;
+        }
+    }
+
+    return;
 
 } ## end of check_prepared_txns
 
 
 sub check_query_runtime {
 
-       ## Make sure a known query runs at least as fast as we think it should
-       ## Supports: Nagios, MRTG
-       ## Warning and critical are time limits, defaulting to seconds
-       ## Valid units: s[econd], m[inute], h[our], d[ay]
-       ## Does a "EXPLAIN ANALYZE SELECT COUNT(1) FROM xyz"
-       ## where xyz is given by the option --queryname
-       ## This could also be a table or a function, or course, but must be a 
-       ## single word. If a function, it must be empty (with "()")
-       ## Examples:
-       ## --warning="100s" --critical="120s" --queryname="speedtest1"
-       ## --warning="5min" --critical="15min" --queryname="speedtest()"
-
-       my ($warning, $critical) = validate_range({type => 'time'});
-
-       my $queryname = $opt{queryname} || '';
-
-       if ($queryname !~ /^[\w\_\.]+(?:\(\))?$/) {
-               ndie msg('runtime-badname');
-       }
-
-       $SQL = "EXPLAIN ANALYZE SELECT COUNT(1) FROM $queryname";
-       my $info = run_command($SQL);
-
-       for $db (@{$info->{db}}) {
-               if (! exists $db->{slurp}[0]{queryplan}) {
-                       add_unknown msg('invalid-query', $db->{slurp});
-                       next;
-               }
-               my $totalms = -1;
-               for my $r (@{$db->{slurp}}) {
-                       if ($r->{queryplan} =~ / (\d+\.\d+) ms/) {
-                               $totalms = $1;
-                       }
-               }
-               my $totalseconds = sprintf '%.2f', $totalms / 1000.0;
-               if ($MRTG) {
-                       $stats{$db->{dbname}} = $totalseconds;
-                       next;
-               }
-               $db->{perf} = " qtime=$totalseconds";
-               my $msg = msg('runtime-msg', $totalseconds);
-               if (length $critical and $totalseconds >= $critical) {
-                       add_critical $msg;
-               }
-               elsif (length $warning and $totalseconds >= $warning) {
-                       add_warning $msg;
-               }
-               else {
-                       add_ok $msg;
-               }
-       }
-
-       $MRTG and do_mrtg_stats(msg('runtime-badmrtg'));
-
-       return;
+    ## Make sure a known query runs at least as fast as we think it should
+    ## Supports: Nagios, MRTG
+    ## Warning and critical are time limits, defaulting to seconds
+    ## Valid units: s[econd], m[inute], h[our], d[ay]
+    ## Does a "EXPLAIN ANALYZE SELECT COUNT(1) FROM xyz"
+    ## where xyz is given by the option --queryname
+    ## This could also be a table or a function, or course, but must be a 
+    ## single word. If a function, it must be empty (with "()")
+    ## Examples:
+    ## --warning="100s" --critical="120s" --queryname="speedtest1"
+    ## --warning="5min" --critical="15min" --queryname="speedtest()"
+
+    my ($warning, $critical) = validate_range({type => 'time'});
+
+    my $queryname = $opt{queryname} || '';
+
+    if ($queryname !~ /^[\w\_\.]+(?:\(\))?$/) {
+        ndie msg('runtime-badname');
+    }
+
+    $SQL = "EXPLAIN ANALYZE SELECT COUNT(1) FROM $queryname";
+    my $info = run_command($SQL);
+
+    for $db (@{$info->{db}}) {
+        if (! exists $db->{slurp}[0]{queryplan}) {
+            add_unknown msg('invalid-query', $db->{slurp});
+            next;
+        }
+        my $totalms = -1;
+        for my $r (@{$db->{slurp}}) {
+            if ($r->{queryplan} =~ / (\d+\.\d+) ms/) {
+                $totalms = $1;
+            }
+        }
+        my $totalseconds = sprintf '%.2f', $totalms / 1000.0;
+        if ($MRTG) {
+            $stats{$db->{dbname}} = $totalseconds;
+            next;
+        }
+        $db->{perf} = " qtime=$totalseconds";
+        my $msg = msg('runtime-msg', $totalseconds);
+        if (length $critical and $totalseconds >= $critical) {
+            add_critical $msg;
+        }
+        elsif (length $warning and $totalseconds >= $warning) {
+            add_warning $msg;
+        }
+        else {
+            add_ok $msg;
+        }
+    }
+
+    $MRTG and do_mrtg_stats(msg('runtime-badmrtg'));
+
+    return;
 
 } ## end of check_query_runtime
 
 
 sub check_query_time {
 
-       ## Check the length of running queries
+    ## Check the length of running queries
 
-       return check_pg_stat_activity(
-               {
-                       default_warning  => '2 minutes',
-                       default_critical => '5 minutes',
-                       whereclause      => q{current_query <> '<IDLE>'},
-                       offsetcol        => q{query_start},
-               });
+    return check_pg_stat_activity(
+        {
+            default_warning  => '2 minutes',
+            default_critical => '5 minutes',
+            whereclause      => q{current_query <> '<IDLE>'},
+            offsetcol        => q{query_start},
+        });
 
 } ## end of check_query_time
 
 
 sub check_relation_size {
 
-       my $relkind = shift || 'relation';
+    my $relkind = shift || 'relation';
 
-       ## Check the size of one or more relations
-       ## Supports: Nagios, MRTG
-       ## By default, checks all relations
-       ## Can check specific one(s) with include
-       ## Can ignore some with exclude
-       ## Warning and critical are bytes
-       ## Valid units: b, k, m, g, t, e
-       ## All above may be written as plural or with a trailing 'g'
-       ## Limit to a specific user (relation owner) with the includeuser option
-       ## Exclude users with the excludeuser option
+    ## Check the size of one or more relations
+    ## Supports: Nagios, MRTG
+    ## By default, checks all relations
+    ## Can check specific one(s) with include
+    ## Can ignore some with exclude
+    ## Warning and critical are bytes
+    ## Valid units: b, k, m, g, t, e
+    ## All above may be written as plural or with a trailing 'g'
+    ## Limit to a specific user (relation owner) with the includeuser option
+    ## Exclude users with the excludeuser option
 
-       my ($warning, $critical) = validate_range({type => 'size'});
+    my ($warning, $critical) = validate_range({type => 'size'});
 
-       $SQL = sprintf q{
+    $SQL = sprintf q{
 SELECT pg_relation_size(c.oid) AS rsize,
   pg_size_pretty(pg_relation_size(c.oid)) AS psize,
   relkind, relname, nspname
 FROM pg_class c, pg_namespace n WHERE (relkind = %s) AND n.oid = c.relnamespace
 },
-       $relkind eq 'table' ? q{'r'}
-       : $relkind eq 'index' ? q{'i'}
-       : q{'r' OR relkind = 'i'};
-
-       if ($opt{perflimit}) {
-               $SQL .= " ORDER BY 1 DESC LIMIT $opt{perflimit}";
-       }
-
-       if ($USERWHERECLAUSE) {
-               $SQL =~ s/ WHERE/, pg_user u WHERE u.usesysid=c.relowner$USERWHERECLAUSE AND/;
-       }
-
-       my $info = run_command($SQL, {emptyok => 1});
-
-       my $found = 0;
-       for $db (@{$info->{db}}) {
-
-               $found = 1;
-               if ($db->{slurp}[0]{rsize} !~ /\d/ and $USERWHERECLAUSE) {
-                       $stats{$db->{dbname}} = 0;
-                       add_ok msg('no-match-user');
-                       next;
-               }
-
-               my ($max,$pmax,$kmax,$nmax,$smax) = (-1,0,0,'?','?');
-
-         ROW: for my $r (@{$db->{slurp}}) {
-                       my ($size,$psize,$kind,$name,$schema) = @$r{qw/ rsize psize relkind relname nspname/};
-
-                       next ROW if skip_item($name, $schema);
-
-                       $db->{perf} .= sprintf "%s%s$name=$size",
-                               $VERBOSE==1 ? "\n" : ' ',
-                               $kind eq 'r' ? "$schema." : '';
-                       ($max=$size, $pmax=$psize, $kmax=$kind, $nmax=$name, $smax=$schema) if $size > $max;
-               }
-               if ($max < 0) {
-                       add_unknown msg('no-match-rel');
-                       next;
-               }
-               if ($MRTG) {
-                       $stats{$db->{dbname}} = $max;
-                       $statsmsg{$db->{dbname}} = sprintf "DB: $db->{dbname} %s %s$nmax",
-                               $kmax eq 'i' ? 'INDEX:' : 'TABLE:', $kmax eq 'i' ? '' : "$smax.";
-                       next;
-               }
-
-               my $msg;
-               if ($relkind eq 'relation') {
-                       if ($kmax eq 'r') {
-                               $msg = msg('relsize-msg-relt', "$smax.$nmax", $pmax);
-                       }
-                       else {
-                               $msg = msg('relsize-msg-reli', $nmax, $pmax);
-                       }
-               }
-               elsif ($relkind eq 'table') {
-                       $msg = msg('relsize-msg-tab', "$smax.$nmax", $pmax);
-               }
-               else {
-                       $msg = msg('relsize-msg-ind', $nmax, $pmax);
-               }
-               if (length $critical and $max >= $critical) {
-                       add_critical $msg;
-               }
-               elsif (length $warning and $max >= $warning) {
-                       add_warning $msg;
-               }
-               else {
-                       add_ok $msg;
-               }
-       }
-
-       return;
+    $relkind eq 'table' ? q{'r'}
+    : $relkind eq 'index' ? q{'i'}
+    : q{'r' OR relkind = 'i'};
+
+    if ($opt{perflimit}) {
+        $SQL .= " ORDER BY 1 DESC LIMIT $opt{perflimit}";
+    }
+
+    if ($USERWHERECLAUSE) {
+        $SQL =~ s/ WHERE/, pg_user u WHERE u.usesysid=c.relowner$USERWHERECLAUSE AND/;
+    }
+
+    my $info = run_command($SQL, {emptyok => 1});
+
+    my $found = 0;
+    for $db (@{$info->{db}}) {
+
+        $found = 1;
+        if ($db->{slurp}[0]{rsize} !~ /\d/ and $USERWHERECLAUSE) {
+            $stats{$db->{dbname}} = 0;
+            add_ok msg('no-match-user');
+            next;
+        }
+
+        my ($max,$pmax,$kmax,$nmax,$smax) = (-1,0,0,'?','?');
+
+      ROW: for my $r (@{$db->{slurp}}) {
+            my ($size,$psize,$kind,$name,$schema) = @$r{qw/ rsize psize relkind relname nspname/};
+
+            next ROW if skip_item($name, $schema);
+
+            $db->{perf} .= sprintf "%s%s$name=$size",
+                $VERBOSE==1 ? "\n" : ' ',
+                $kind eq 'r' ? "$schema." : '';
+            ($max=$size, $pmax=$psize, $kmax=$kind, $nmax=$name, $smax=$schema) if $size > $max;
+        }
+        if ($max < 0) {
+            add_unknown msg('no-match-rel');
+            next;
+        }
+        if ($MRTG) {
+            $stats{$db->{dbname}} = $max;
+            $statsmsg{$db->{dbname}} = sprintf "DB: $db->{dbname} %s %s$nmax",
+                $kmax eq 'i' ? 'INDEX:' : 'TABLE:', $kmax eq 'i' ? '' : "$smax.";
+            next;
+        }
+
+        my $msg;
+        if ($relkind eq 'relation') {
+            if ($kmax eq 'r') {
+                $msg = msg('relsize-msg-relt', "$smax.$nmax", $pmax);
+            }
+            else {
+                $msg = msg('relsize-msg-reli', $nmax, $pmax);
+            }
+        }
+        elsif ($relkind eq 'table') {
+            $msg = msg('relsize-msg-tab', "$smax.$nmax", $pmax);
+        }
+        else {
+            $msg = msg('relsize-msg-ind', $nmax, $pmax);
+        }
+        if (length $critical and $max >= $critical) {
+            add_critical $msg;
+        }
+        elsif (length $warning and $max >= $warning) {
+            add_warning $msg;
+        }
+        else {
+            add_ok $msg;
+        }
+    }
+
+    return;
 
 } ## end of check_relation_size
 
 
 sub check_table_size {
-       return check_relation_size('table');
+    return check_relation_size('table');
 }
 sub check_index_size {
-       return check_relation_size('index');
+    return check_relation_size('index');
 }
 
 
 sub check_replicate_row {
 
-       ## Make an update on one server, make sure it propogates to others
-       ## Supports: Nagios, MRTG
-       ## Warning and critical are time to replicate to all slaves
-
-       my ($warning, $critical) = validate_range({type => 'time', leastone => 1, forcemrtg => 1});
-
-       if ($warning and $critical and $warning > $critical) {
-               ndie msg('range-warnbig');
-       }
-
-       if (!$opt{repinfo}) {
-               ndie msg('rep-noarg');
-       }
-       my @repinfo = split /,/ => ($opt{repinfo} || '');
-       if ($#repinfo != 5) {
-               ndie msg('rep-badarg');
-       }
-       my ($table,$pk,$id,$col,$val1,$val2) = (@repinfo);
-
-       ## Quote everything, just to be safe (e.g. columns named 'desc')
-       $table = qq{"$table"};
-       $pk    = qq{"$pk"};
-       $col   = qq{"$col"};
-
-       if ($val1 eq $val2) {
-               ndie msg('rep-duh');
-       }
-
-       $SQL = qq{UPDATE $table SET $col = 'X' WHERE $pk = '$id'};
-       (my $update1 = $SQL) =~ s/X/$val1/;
-       (my $update2 = $SQL) =~ s/X/$val2/;
-       my $select = qq{SELECT $col AS c FROM $table WHERE $pk = '$id'};
-
-       ## Are they the same on both sides? Must be yes, or we error out
-
-       ## We assume this is a single server
-       my $info1 = run_command($select);
-       ## Squirrel away the $db setting for later
-       my $sourcedb = $info1->{db}[0];
-       if (!defined $sourcedb) {
-               ndie msg('rep-norow', "$table.$col");
-       }
-       my $value1 = $info1->{db}[0]{slurp}[0]{c};
-
-       my $info2 = run_command($select, { dbnumber => 2 });
-       my $slave = 0;
-       for my $d (@{$info2->{db}}) {
-               $slave++;
-               my $value2 = $d->{slurp}[0]{c};
-               if ($value1 ne $value2) {
-                       ndie msg('rep-notsame');
-               }
-       }
-       my $numslaves = $slave;
-       if ($numslaves < 1) {
-               ndie msg('rep-noslaves');
-       }
-
-       my ($update,$newval);
-       if ($value1 eq $val1) {
-               $update = $update2;
-               $newval = $val2;
-       }
-       elsif ($value1 eq $val2) {
-               $update = $update1;
-               $newval = $val1;
-       }
-       else {
-               ndie msg('rep-wrongvals', $value1, $val1, $val2);
-       }
-
-       $info1 = run_command($update, { failok => 1 } );
-
-       ## Make sure the update worked
-       if (! defined $info1->{db}[0]) {
-               ndie msg('rep-sourcefail');
-       }
-
-       my $err = $info1->{db}[0]{error} || '';
-       if ($err) {
-               $err =~ s/ERROR://; ## e.g. Slony read-only
-               ndie $err;
-       }
-
-       ## Start the clock
-       my $starttime = time();
-
-       ## Loop until we get a match, check each in turn
-       my %slave;
-       my $time = 0;
-       LOOP: {
-               $info2 = run_command($select, { dbnumber => 2 } );
-               ## Reset for final output
-               $db = $sourcedb;
-
-               $slave = 0;
-               for my $d (@{$info2->{db}}) {
-                       $slave++;
-                       next if exists $slave{$slave};
-                       my $value2 = $d->{slurp}[0]{c};
-                       $time = $db->{totaltime} = time - $starttime;
-                       if ($value2 eq $newval) {
-                               $slave{$slave} = $time;
-                               next;
-                       }
-                       if ($warning and $time > $warning) {
-                               $MRTG and do_mrtg({one => 0, msg => $time});
-                               add_warning msg('rep-fail', $slave);
-                               return;
-                       }
-                       elsif ($critical and $time > $critical) {
-                               $MRTG and do_mrtg({one => 0, msg => $time});
-                               add_critical msg('rep-fail', $slave);
-                               return;
-                       }
-               }
-               ## Did they all match?
-               my $k = keys %slave;
-               if (keys %slave >= $numslaves) {
-                       $MRTG and do_mrtg({one => $time});
-                       add_ok msg('rep-ok');
-                       return;
-               }
-               sleep 1;
-               redo;
-       }
-
-       $MRTG and ndie msg('rep-timeout', $time);
-       add_unknown msg('rep-unknown');
-       return;
+    ## Make an update on one server, make sure it propogates to others
+    ## Supports: Nagios, MRTG
+    ## Warning and critical are time to replicate to all slaves
+
+    my ($warning, $critical) = validate_range({type => 'time', leastone => 1, forcemrtg => 1});
+
+    if ($warning and $critical and $warning > $critical) {
+        ndie msg('range-warnbig');
+    }
+
+    if (!$opt{repinfo}) {
+        ndie msg('rep-noarg');
+    }
+    my @repinfo = split /,/ => ($opt{repinfo} || '');
+    if ($#repinfo != 5) {
+        ndie msg('rep-badarg');
+    }
+    my ($table,$pk,$id,$col,$val1,$val2) = (@repinfo);
+
+    ## Quote everything, just to be safe (e.g. columns named 'desc')
+    $table = qq{"$table"};
+    $pk    = qq{"$pk"};
+    $col   = qq{"$col"};
+
+    if ($val1 eq $val2) {
+        ndie msg('rep-duh');
+    }
+
+    $SQL = qq{UPDATE $table SET $col = 'X' WHERE $pk = '$id'};
+    (my $update1 = $SQL) =~ s/X/$val1/;
+    (my $update2 = $SQL) =~ s/X/$val2/;
+    my $select = qq{SELECT $col AS c FROM $table WHERE $pk = '$id'};
+
+    ## Are they the same on both sides? Must be yes, or we error out
+
+    ## We assume this is a single server
+    my $info1 = run_command($select);
+    ## Squirrel away the $db setting for later
+    my $sourcedb = $info1->{db}[0];
+    if (!defined $sourcedb) {
+        ndie msg('rep-norow', "$table.$col");
+    }
+    my $value1 = $info1->{db}[0]{slurp}[0]{c};
+
+    my $info2 = run_command($select, { dbnumber => 2 });
+    my $slave = 0;
+    for my $d (@{$info2->{db}}) {
+        $slave++;
+        my $value2 = $d->{slurp}[0]{c};
+        if ($value1 ne $value2) {
+            ndie msg('rep-notsame');
+        }
+    }
+    my $numslaves = $slave;
+    if ($numslaves < 1) {
+        ndie msg('rep-noslaves');
+    }
+
+    my ($update,$newval);
+    if ($value1 eq $val1) {
+        $update = $update2;
+        $newval = $val2;
+    }
+    elsif ($value1 eq $val2) {
+        $update = $update1;
+        $newval = $val1;
+    }
+    else {
+        ndie msg('rep-wrongvals', $value1, $val1, $val2);
+    }
+
+    $info1 = run_command($update, { failok => 1 } );
+
+    ## Make sure the update worked
+    if (! defined $info1->{db}[0]) {
+        ndie msg('rep-sourcefail');
+    }
+
+    my $err = $info1->{db}[0]{error} || '';
+    if ($err) {
+        $err =~ s/ERROR://; ## e.g. Slony read-only
+        ndie $err;
+    }
+
+    ## Start the clock
+    my $starttime = time();
+
+    ## Loop until we get a match, check each in turn
+    my %slave;
+    my $time = 0;
+    LOOP: {
+        $info2 = run_command($select, { dbnumber => 2 } );
+        ## Reset for final output
+        $db = $sourcedb;
+
+        $slave = 0;
+        for my $d (@{$info2->{db}}) {
+            $slave++;
+            next if exists $slave{$slave};
+            my $value2 = $d->{slurp}[0]{c};
+            $time = $db->{totaltime} = time - $starttime;
+            if ($value2 eq $newval) {
+                $slave{$slave} = $time;
+                next;
+            }
+            if ($warning and $time > $warning) {
+                $MRTG and do_mrtg({one => 0, msg => $time});
+                add_warning msg('rep-fail', $slave);
+                return;
+            }
+            elsif ($critical and $time > $critical) {
+                $MRTG and do_mrtg({one => 0, msg => $time});
+                add_critical msg('rep-fail', $slave);
+                return;
+            }
+        }
+        ## Did they all match?
+        my $k = keys %slave;
+        if (keys %slave >= $numslaves) {
+            $MRTG and do_mrtg({one => $time});
+            add_ok msg('rep-ok');
+            return;
+        }
+        sleep 1;
+        redo;
+    }
+
+    $MRTG and ndie msg('rep-timeout', $time);
+    add_unknown msg('rep-unknown');
+    return;
 
 } ## end of check_replicate_row
 
 
 sub check_same_schema {
 
-       ## Verify that all relations inside two databases are the same
-       ## Supports: Nagios
-       ## Include and exclude should be supported
-       ## Warning and critical are not used as normal
-       ## Warning is used to do filtering
-
-       ## Check for filtering rules
-       my %filter;
-       if (exists $opt{warning} and length $opt{warning}) {
-               for my $phrase (split /[\s,]+/ => $opt{warning}) {
-                       for my $type (qw/schema user table view index sequence constraint trigger function perm language owner/) {
-                               if ($phrase =~ /^no${type}s?$/i) {
-                                       $filter{"no${type}s"} = 1;
-                               }
-                               elsif ($phrase =~ /^no$type=(.+)/i) {
-                                       push @{$filter{"no${type}_regex"}} => $1;
-                               }
-                       }
-                       if ($phrase =~ /^noposition$/io) { ## no critic (ProhibitFixedStringMatches)
-                               $filter{noposition} = 1;
-                       }
-                       if ($phrase =~ /^nofuncbody$/io) { ## no critic (ProhibitFixedStringMatches)
-                               $filter{nofuncbody} = 1;
-                       }
-               }
-               $VERBOSE >= 3 and warn Dumper \%filter;
-       }
-
-       my (%thing,$info);
-
-       ## Do some synchronizations: assume db "1" is the default for "2" unless explicitly set
-       for my $setting (qw/ host port dbname dbuser dbpass dbservice /) {
-               my $two = "${setting}2";
-               if (exists $opt{$setting} and ! exists $opt{$two}) {
-                       $opt{$two} = $opt{$setting};
-               }
-       }
-
-       my $saved_db;
-       for my $x (1..2) {
-
-               ## Get a list of all users
-               if (! exists $filter{nousers}) {
-                       $SQL = q{
+    ## Verify that all relations inside two databases are the same
+    ## Supports: Nagios
+    ## Include and exclude should be supported
+    ## Warning and critical are not used as normal
+    ## Warning is used to do filtering
+
+    ## Check for filtering rules
+    my %filter;
+    if (exists $opt{warning} and length $opt{warning}) {
+        for my $phrase (split /[\s,]+/ => $opt{warning}) {
+            for my $type (qw/schema user table view index sequence constraint trigger function perm language owner/) {
+                if ($phrase =~ /^no${type}s?$/i) {
+                    $filter{"no${type}s"} = 1;
+                }
+                elsif ($phrase =~ /^no$type=(.+)/i) {
+                    push @{$filter{"no${type}_regex"}} => $1;
+                }
+            }
+            if ($phrase =~ /^noposition$/io) { ## no critic (ProhibitFixedStringMatches)
+                $filter{noposition} = 1;
+            }
+            if ($phrase =~ /^nofuncbody$/io) { ## no critic (ProhibitFixedStringMatches)
+                $filter{nofuncbody} = 1;
+            }
+        }
+        $VERBOSE >= 3 and warn Dumper \%filter;
+    }
+
+    my (%thing,$info);
+
+    ## Do some synchronizations: assume db "1" is the default for "2" unless explicitly set
+    for my $setting (qw/ host port dbname dbuser dbpass dbservice /) {
+        my $two = "${setting}2";
+        if (exists $opt{$setting} and ! exists $opt{$two}) {
+            $opt{$two} = $opt{$setting};
+        }
+    }
+
+    my $saved_db;
+    for my $x (1..2) {
+
+        ## Get a list of all users
+        if (! exists $filter{nousers}) {
+            $SQL = q{
 SELECT usesysid, quote_ident(usename) AS usename, usecreatedb, usesuper
 FROM pg_user
 };
-                       $info = run_command($SQL, { dbuser => $opt{dbuser}[$x-1], dbnumber => $x } );
-                       for $db (@{$info->{db}}) {
-                               for my $r (@{$db->{slurp}}) {
-                                       $thing{$x}{users}{$r->{usename}} = {
-                                               oid=>$r->{usesysid},
-                                               createdb=>$r->{usecreatedb},
-                                               superuser=>$r->{usesuper}
-                                       };
-                                       $thing{$x}{useroid}{$r->{usesysid}} = $r->{usename};
-                               }
-                       }
-               }
-
-               ## Get a list of all schemas (aka namespaces)
-               if (! exists $filter{noschemas}) {
-                       $SQL = q{
+            $info = run_command($SQL, { dbuser => $opt{dbuser}[$x-1], dbnumber => $x } );
+            for $db (@{$info->{db}}) {
+                for my $r (@{$db->{slurp}}) {
+                    $thing{$x}{users}{$r->{usename}} = {
+                        oid=>$r->{usesysid},
+                        createdb=>$r->{usecreatedb},
+                        superuser=>$r->{usesuper}
+                    };
+                    $thing{$x}{useroid}{$r->{usesysid}} = $r->{usename};
+                }
+            }
+        }
+
+        ## Get a list of all schemas (aka namespaces)
+        if (! exists $filter{noschemas}) {
+            $SQL = q{
 SELECT quote_ident(nspname) AS nspname, n.oid, quote_ident(usename) AS usename, nspacl
 FROM pg_namespace n
 JOIN pg_user u ON (u.usesysid = n.nspowner)
 WHERE nspname !~ '^pg_t'
 };
-                       $info = run_command($SQL, { dbuser => $opt{dbuser}[$x-1], dbnumber => $x } );
-                       for $db (@{$info->{db}}) {
-                               for my $r (@{$db->{slurp}}) {
-                                       $thing{$x}{schemas}{$r->{nspname}} = {
-                                               oid   => $r->{oid},
-                                               owner => $r->{usename},
-                                               acl   => (exists $filter{noperms} or !$r->{nspacl}) ? '(none)' : $r->{nspacl},
-                                       };
-                               }
-                       }
-               }
-
-               ## Get a list of all relations
-               if (! exists $filter{notables}) {
-                       $SQL = q{
+            $info = run_command($SQL, { dbuser => $opt{dbuser}[$x-1], dbnumber => $x } );
+            for $db (@{$info->{db}}) {
+                for my $r (@{$db->{slurp}}) {
+                    $thing{$x}{schemas}{$r->{nspname}} = {
+                        oid   => $r->{oid},
+                        owner => $r->{usename},
+                        acl   => (exists $filter{noperms} or !$r->{nspacl}) ? '(none)' : $r->{nspacl},
+                    };
+                }
+            }
+        }
+
+        ## Get a list of all relations
+        if (! exists $filter{notables}) {
+            $SQL = q{
 SELECT relkind, quote_ident(nspname) AS nspname, quote_ident(relname) AS relname, 
   quote_ident(usename) AS usename, relacl,
   CASE WHEN relkind = 'v' THEN pg_get_viewdef(c.oid) ELSE '' END AS viewdef
@@ -4965,73 +4965,73 @@ JOIN pg_namespace n ON (n.oid = c.relnamespace)
 JOIN pg_user u ON (u.usesysid = c.relowner)
 WHERE nspname !~ '^pg_t'
 };
-                       exists $filter{notriggers}  and $SQL .= q{ AND relkind <> 'r'};
-                       exists $filter{noviews}     and $SQL .= q{ AND relkind <> 'v'};
-                       exists $filter{noindexes}   and $SQL .= q{ AND relkind <> 'i'};
-                       exists $filter{nosequences} and $SQL .= q{ AND relkind <> 'S'};
-                       $info = run_command($SQL, { dbuser => $opt{dbuser}[$x-1], dbnumber => $x } );
-                       for $db (@{$info->{db}}) {
-                               for my $r (@{$db->{slurp}}) {
-                                       my ($kind,$schema,$name,$owner,$acl,$def) = @$r{
-                                               qw/ relkind nspname relname usename relacl viewdef /};
-                                       $acl = '(none)' if exists $filter{noperms};
-                                       if ($kind eq 'r') {
-                                               $thing{$x}{tables}{"$schema.$name"} =
-                                               {
-                                                schema=>$schema, table=>$name, owner=>$owner, acl=>$acl||'(none)' };
-                                       }
-                                       elsif ($kind eq 'v') {
-                                               $thing{$x}{views}{"$schema.$name"} =
-                                               {
-                                                schema=>$schema, table=>$name, owner=>$owner, acl=>$acl||'(none)', def=>$def };
-                                       }
-                                       elsif ($kind eq 'i') {
-                                               $thing{$x}{indexes}{"$schema.$name"} =
-                                               {
-                                                schema=>$schema, table=>$name, owner=>$owner, acl=>$acl||'(none)' };
-                                       }
-                                       elsif ($kind eq 'S') {
-                                               $thing{$x}{sequences}{"$schema.$name"} =
-                                               {
-                                                schema=>$schema, table=>$name, owner=>$owner, acl=>$acl||'(none)' };
-                                       }
-                               }
-                       }
-               }
-
-               ## Get a list of all types
-               $SQL = q{SELECT typname, oid FROM pg_type};
-               $info = run_command($SQL, { dbuser => $opt{dbuser}[$x-1], dbnumber => $x } );
-               for $db (@{$info->{db}}) {
-                       for my $r (@{$db->{slurp}}) {
-                               $thing{$x}{type}{$r->{oid}} = $r->{typname};
-                       }
-                       $saved_db = $db if ! defined $saved_db;
-               }
-
-               ## Get a list of all triggers
-               if (! exists $filter{notriggers}) {
-                       $SQL = q{
+            exists $filter{notriggers}  and $SQL .= q{ AND relkind <> 'r'};
+            exists $filter{noviews}     and $SQL .= q{ AND relkind <> 'v'};
+            exists $filter{noindexes}   and $SQL .= q{ AND relkind <> 'i'};
+            exists $filter{nosequences} and $SQL .= q{ AND relkind <> 'S'};
+            $info = run_command($SQL, { dbuser => $opt{dbuser}[$x-1], dbnumber => $x } );
+            for $db (@{$info->{db}}) {
+                for my $r (@{$db->{slurp}}) {
+                    my ($kind,$schema,$name,$owner,$acl,$def) = @$r{
+                        qw/ relkind nspname relname usename relacl viewdef /};
+                     $acl = '(none)' if exists $filter{noperms};
+                    if ($kind eq 'r') {
+                        $thing{$x}{tables}{"$schema.$name"} =
+                        {
+                         schema=>$schema, table=>$name, owner=>$owner, acl=>$acl||'(none)' };
+                    }
+                    elsif ($kind eq 'v') {
+                        $thing{$x}{views}{"$schema.$name"} =
+                        {
+                         schema=>$schema, table=>$name, owner=>$owner, acl=>$acl||'(none)', def=>$def };
+                    }
+                    elsif ($kind eq 'i') {
+                        $thing{$x}{indexes}{"$schema.$name"} =
+                        {
+                         schema=>$schema, table=>$name, owner=>$owner, acl=>$acl||'(none)' };
+                    }
+                    elsif ($kind eq 'S') {
+                        $thing{$x}{sequences}{"$schema.$name"} =
+                        {
+                         schema=>$schema, table=>$name, owner=>$owner, acl=>$acl||'(none)' };
+                    }
+                }
+            }
+        }
+
+        ## Get a list of all types
+        $SQL = q{SELECT typname, oid FROM pg_type};
+        $info = run_command($SQL, { dbuser => $opt{dbuser}[$x-1], dbnumber => $x } );
+        for $db (@{$info->{db}}) {
+            for my $r (@{$db->{slurp}}) {
+                $thing{$x}{type}{$r->{oid}} = $r->{typname};
+            }
+            $saved_db = $db if ! defined $saved_db;
+        }
+
+        ## Get a list of all triggers
+        if (! exists $filter{notriggers}) {
+            $SQL = q{
 SELECT tgname, quote_ident(relname) AS relname, proname, proargtypes
 FROM pg_trigger
 JOIN pg_class c ON (c.oid = tgrelid)
 JOIN pg_proc p ON (p.oid = tgfoid)
 WHERE NOT tgisconstraint
 }; ## constraints checked separately
-                       $info = run_command($SQL, { dbuser => $opt{dbuser}[$x-1], dbnumber => $x } );
-                       for $db (@{$info->{db}}) {
-                               for my $r (@{$db->{slurp}}) {
-                                       my ($name,$table,$func,$args) = @$r{qw/ tgname relname proname proargtypes /};
-                                       $args =~ s/(\d+)/$thing{$x}{type}{$1}/g;
-                                       $args =~ s/^\s*(.*)\s*$/($1)/;
-                                       $thing{$x}{triggers}{$name} = { table=>$table, func=>$func, args=>$args };
-                               }
-                       }
-               }
-
-               ## Get a list of all columns
-               ## We'll use information_schema for this one
-               $SQL = q{
+            $info = run_command($SQL, { dbuser => $opt{dbuser}[$x-1], dbnumber => $x } );
+            for $db (@{$info->{db}}) {
+                for my $r (@{$db->{slurp}}) {
+                    my ($name,$table,$func,$args) = @$r{qw/ tgname relname proname proargtypes /};
+                    $args =~ s/(\d+)/$thing{$x}{type}{$1}/g;
+                    $args =~ s/^\s*(.*)\s*$/($1)/;
+                    $thing{$x}{triggers}{$name} = { table=>$table, func=>$func, args=>$args };
+                }
+            }
+        }
+
+        ## Get a list of all columns
+        ## We'll use information_schema for this one
+        $SQL = q{
 SELECT table_schema AS ts, table_name AS tn, column_name AS cn, ordinal_position AS op,
   COALESCE(column_default, '(none)') AS df,
   is_nullable AS in, data_type AS dt,
@@ -5041,58 +5041,58 @@ SELECT table_schema AS ts, table_name AS tn, column_name AS cn, ordinal_position
 FROM information_schema.columns
 ORDER BY table_schema, table_name, ordinal_position, column_name
 };
-               $info = run_command($SQL, { dbuser => $opt{dbuser}[$x-1], dbnumber => $x } );
-               my $oldrelation = '';
-               my $col = 0;
-               my $position;
-               for $db (@{$info->{db}}) {
-                       for my $r (@{$db->{slurp}}) {
-
-                               my ($schema,$table) = @$r{qw/ ts tn /};
-
-                               ## If this is a new relation, reset the column numbering
-                               if ($oldrelation ne "$schema.$table") {
-                                       $oldrelation = "$schema.$table";
-                                       $col = 1;
-                               }
-
-                               ## Rather than use ordinal_position directly, count the live columns
-                               $position = $col++;
-
-                               $thing{$x}{columns}{"$schema.$table"}{$r->{cn}} = {
-                                       schema     => $schema,
-                                       table      => $table,
-                                       name       => $r->{cn},
-                                       position   => exists $filter{noposition} ? 0 : $position,
-                                       default    => $r->{df},
-                                       nullable   => $r->{in},
-                                       type       => $r->{dt},
-                                       length     => $r->{ml},
-                                       precision  => $r->{np},
-                                       scale      => $r->{ns},
-                               };
-                       }
-               }
-
-               ## Get a list of all constraints
-               ## We'll use information_schema for this one too
-               if (! exists $filter{noconstraints}) {
-                       $SQL = q{
+        $info = run_command($SQL, { dbuser => $opt{dbuser}[$x-1], dbnumber => $x } );
+        my $oldrelation = '';
+        my $col = 0;
+        my $position;
+        for $db (@{$info->{db}}) {
+            for my $r (@{$db->{slurp}}) {
+
+                my ($schema,$table) = @$r{qw/ ts tn /};
+
+                ## If this is a new relation, reset the column numbering
+                if ($oldrelation ne "$schema.$table") {
+                    $oldrelation = "$schema.$table";
+                    $col = 1;
+                }
+
+                ## Rather than use ordinal_position directly, count the live columns
+                $position = $col++;
+
+                $thing{$x}{columns}{"$schema.$table"}{$r->{cn}} = {
+                    schema     => $schema,
+                    table      => $table,
+                    name       => $r->{cn},
+                    position   => exists $filter{noposition} ? 0 : $position,
+                    default    => $r->{df},
+                    nullable   => $r->{in},
+                    type       => $r->{dt},
+                    length     => $r->{ml},
+                    precision  => $r->{np},
+                    scale      => $r->{ns},
+                };
+            }
+        }
+
+        ## Get a list of all constraints
+        ## We'll use information_schema for this one too
+        if (! exists $filter{noconstraints}) {
+            $SQL = q{
 SELECT constraint_schema AS cs, constraint_name AS cn, table_schema AS ts, table_name AS tn
 FROM information_schema.constraint_table_usage
 };
-                       $info = run_command($SQL, { dbuser => $opt{dbuser}[$x-1], dbnumber => $x } );
-                       for $db (@{$info->{db}}) {
-                               for my $r (@{$db->{slurp}}) {
-                                       my ($ichi,$ni,$san,$shi) = @$r{qw/ cs cn ts tn/};
-
-                                       ## No sense in grabbing "generic" constraints
-                                       next if $ni =~ /^\$\d+$/o;
-
-                                       $thing{$x}{constraints}{"$ichi.$ni"} = "$san.$shi";
-                               }
-                       }
-                       $SQL = <<'SQL';  # cribbed from information_schema.constraint_column_usage
+            $info = run_command($SQL, { dbuser => $opt{dbuser}[$x-1], dbnumber => $x } );
+            for $db (@{$info->{db}}) {
+                for my $r (@{$db->{slurp}}) {
+                    my ($ichi,$ni,$san,$shi) = @$r{qw/ cs cn ts tn/};
+
+                    ## No sense in grabbing "generic" constraints
+                    next if $ni =~ /^\$\d+$/o;
+
+                    $thing{$x}{constraints}{"$ichi.$ni"} = "$san.$shi";
+                }
+            }
+            $SQL = <<'SQL';  # cribbed from information_schema.constraint_column_usage
 SELECT current_database()::information_schema.sql_identifier AS cd,
   x.tblschema::information_schema.sql_identifier AS tschema,
   x.tblname::information_schema.sql_identifier AS tname,
@@ -5134,1138 +5134,1138 @@ FROM (( SELECT DISTINCT nr.nspname, r.relname, r.relowner, a.attname, nc.nspname
   x(tblschema, tblname, tblowner, colname, cstrschema, cstrname, constrdef)
 WHERE pg_has_role(x.tblowner, 'USAGE'::text)
 SQL
-                       $info = run_command($SQL, { dbuser => $opt{dbuser}[$x-1], dbnumber => $x } );
-                       for $db (@{$info->{db}}) {
-                               for my $r (@{$db->{slurp}}) {
-                                       my ($cschema,$cname,$tschema,$tname,$ccol,$cdef) = @$r{
-                                               qw/cschema cname tschema tname ccol cdef/};
-                                       ## No sense in grabbing "generic" constraints
-                                       if ($cname !~ /^\$\d+$/o) {
-                                               if (exists $thing{$x}{colconstraints}{"$cschema.$cname"}) {
-                                                       my @oldcols = split / / => $thing{$x}{colconstraints}{"$cschema.$cname"}->[1];
-                                                       push @oldcols => $ccol;
-                                                       $ccol = join ' ' => sort @oldcols;
-                                               }
-                                               $thing{$x}{colconstraints}{"$cschema.$cname"} = ["$tschema.$tname", $ccol, $cdef];
-                                       }
-                               }
-                       }
-               }
-
-               ## Get a list of all functions
-               if (! exists $filter{nofunctions}) {
-                       $SQL = q{
+            $info = run_command($SQL, { dbuser => $opt{dbuser}[$x-1], dbnumber => $x } );
+            for $db (@{$info->{db}}) {
+                for my $r (@{$db->{slurp}}) {
+                    my ($cschema,$cname,$tschema,$tname,$ccol,$cdef) = @$r{
+                        qw/cschema cname tschema tname ccol cdef/};
+                    ## No sense in grabbing "generic" constraints
+                    if ($cname !~ /^\$\d+$/o) {
+                        if (exists $thing{$x}{colconstraints}{"$cschema.$cname"}) {
+                            my @oldcols = split / / => $thing{$x}{colconstraints}{"$cschema.$cname"}->[1];
+                            push @oldcols => $ccol;
+                            $ccol = join ' ' => sort @oldcols;
+                        }
+                        $thing{$x}{colconstraints}{"$cschema.$cname"} = ["$tschema.$tname", $ccol, $cdef];
+                    }
+                }
+            }
+        }
+
+        ## Get a list of all functions
+        if (! exists $filter{nofunctions}) {
+            $SQL = q{
 SELECT quote_ident(nspname) AS nspname, quote_ident(proname) AS proname, proargtypes, md5(prosrc) AS md,
   proisstrict, proretset, provolatile
 FROM pg_proc
 JOIN pg_namespace n ON (n.oid = pronamespace)
 };
-                       $info = run_command($SQL, { dbuser => $opt{dbuser}[$x-1], dbnumber => $x } );
-                       for $db (@{$info->{db}}) {
-                               for my $r (@{$db->{slurp}}) {
-                                       my ($schema,$name,$args,$md5,$isstrict,$retset,$volatile) = @$r{
-                                               qw/ nspname proname proargtypes md proisstrict proretset provolatile /};
-                                       $args =~ s/ /,/g;
-                                       $args =~ s/(\d+)/$thing{$x}{type}{$1}/g;
-                                       $args =~ s/^\s*(.*)\s*$/($1)/;
-                                       $thing{$x}{functions}{"${schema}.${name}${args}"} = {
-                                               md5 => $md5,
-                                               isstrict => $isstrict,
-                                               retset => $retset,
-                                               volatile => $volatile,
-                                       };
-                               }
-                       }
-               }
-
-               ## Get a list of all languages
-               if (! exists $filter{nolanguages}) {
-                       $SQL = q{SELECT lanname FROM pg_language};
-                       $info = run_command($SQL, { dbuser => $opt{dbuser}[$x-1], dbnumber => $x } );
-                       for $db (@{$info->{db}}) {
-                               for my $r (@{$db->{slurp}}) {
-                                       $thing{$x}{language}{$r->{lanname}} = 1;
-                               }
-                       }
-               }
-
-
-       } ## end each database to query
-
-       $db = $saved_db;
-
-       ## Build a list of what has failed
-       my %fail;
-       my $failcount = 0;
-
-       ## Compare users
-
-       ## Any users on 1 but not 2?
-       USER1:
-       for my $user (sort keys %{$thing{1}{users}}) {
-               next if exists $thing{2}{users}{$user};
-
-               if (exists $filter{nouser_regex}) {
-                       for my $regex (@{$filter{nouser_regex}}) {
-                               next USER1 if $user =~ /$regex/;
-                       }
-               }
-
-               push @{$fail{users}{notexist}{1}} => $user;
-               $failcount++;
-       }
-
-       ## Any users on 2 but not 1?
-       USER2:
-       for my $user (sort keys %{$thing{2}{users}}) {
-
-               if (exists $filter{nouser_regex}) {
-                       for my $regex (@{$filter{nouser_regex}}) {
-                               next USER2 if $user =~ /$regex/;
-                       }
-               }
-
-               if (! exists $thing{1}{users}{$user}) {
-                       push @{$fail{users}{notexist}{2}} => $user;
-                       $failcount++;
-                       next;
-               }
-               ## Do the matching users have the same superpowers?
-
-               if ($thing{1}{users}{$user}{createdb} ne $thing{2}{users}{$user}{createdb}) {
-                       push @{$fail{users}{createdb}{1}{$thing{1}{users}{$user}{createdb}}} => $user;
-                       $failcount++;
-               }
-
-               if ($thing{1}{users}{$user}{superuser} ne $thing{2}{users}{$user}{superuser}) {
-                       push @{$fail{users}{superuser}{1}{$thing{1}{users}{$user}{superuser}}} => $user;
-                       $failcount++;
-               }
-       }
-
-       ## Compare schemas
-
-       ## Any schemas on 1 but not 2?
-       SCHEMA1:
-       for my $name (sort keys %{$thing{1}{schemas}}) {
-               next if exists $thing{2}{schemas}{$name};
-
-               if (exists $filter{noschema_regex}) {
-                       for my $regex (@{$filter{noschema_regex}}) {
-                               next SCHEMA1 if $name =~ /$regex/;
-                       }
-               }
-
-               push @{$fail{schemas}{notexist}{1}} => $name;
-               $failcount++;
-       }
-
-       ## Any schemas on 2 but not 1?
-       SCHEMA2:
-       for my $name (sort keys %{$thing{2}{schemas}}) {
-
-               if (exists $filter{noschema_regex}) {
-                       for my $regex (@{$filter{noschema_regex}}) {
-                               next SCHEMA2 if $name =~ /$regex/;
-                       }
-               }
-
-               if (! exists $thing{1}{schemas}{$name}) {
-                       push @{$fail{schemas}{notexist}{2}} => $name;
-                       $failcount++;
-                       next;
-               }
-
-               ## Do the schemas have same owner and permissions?
-               if (! exists $filter{noowners}) {
-                       if ($thing{1}{schemas}{$name}{owner} ne $thing{2}{schemas}{$name}{owner}) {
-                               push @{$fail{schemas}{diffowners}} =>
-                                       [
-                                               $name,
-                                               $thing{1}{schemas}{$name}{owner},
-                                               $thing{2}{schemas}{$name}{owner},
-                               ];
-                               $failcount++;
-                       }
-               }
-
-               if ($thing{1}{schemas}{$name}{acl} ne $thing{2}{schemas}{$name}{acl}) {
-                       push @{$fail{schemas}{diffacls}} =>
-                               [
-                                       $name,
-                                       $thing{1}{schemas}{$name}{acl},
-                                       $thing{2}{schemas}{$name}{acl},
-                               ];
-                       $failcount++;
-               }
-
-       }
-
-       ## Compare tables
-
-       ## Any tables on 1 but not 2?
-       ## We treat the name as a unified "schema.relname"
-       TABLE1:
-       for my $name (sort keys %{$thing{1}{tables}}) {
-               next if exists $thing{2}{tables}{$name};
-
-               ## If the schema does not exist, don't bother reporting it
-               next if ! exists $thing{2}{schemas}{ $thing{1}{tables}{$name}{schema} };
-
-               if (exists $filter{notable_regex}) {
-                       for my $regex (@{$filter{notable_regex}}) {
-                               next TABLE1 if $name =~ /$regex/;
-                       }
-               }
-
-               for my $exclude (@{$opt{exclude}}) {
-                       next TABLE1 if $name =~ /$exclude/;
-               }
-
-               push @{$fail{tables}{notexist}{1}} => $name;
-               $failcount++;
-       }
-
-       ## Any tables on 2 but not 1?
-       TABLE2:
-       for my $name (sort keys %{$thing{2}{tables}}) {
-
-               if (exists $filter{notable_regex}) {
-                       for my $regex (@{$filter{notable_regex}}) {
-                               next TABLE2 if $name =~ /$regex/;
-                       }
-               }
-
-               for my $exclude (@{$opt{exclude}}) {
-                       next TABLE2 if $name =~ /$exclude/;
-               }
-
-               if (! exists $thing{1}{tables}{$name}) {
-                       ## If the schema does not exist, don't bother reporting it
-                       if (exists $thing{1}{schemas}{ $thing{2}{tables}{$name}{schema} }) {
-                               push @{$fail{tables}{notexist}{2}} => $name;
-                               $failcount++;
-                       }
-                       next;
-               }
-
-               ## Do the tables have same owner and permissions?
-               if (! exists $filter{noowners}) {
-                       if ($thing{1}{tables}{$name}{owner} ne $thing{2}{tables}{$name}{owner}) {
-                               push @{$fail{tables}{diffowners}} =>
-                                       [
-                                               $name,
-                                               $thing{1}{tables}{$name}{owner},
-                                               $thing{2}{tables}{$name}{owner},
-                               ];
-                               $failcount++;
-                       }
-               }
-
-               if ($thing{1}{tables}{$name}{acl} ne $thing{2}{tables}{$name}{acl}) {
-                       push @{$fail{tables}{diffacls}} =>
-                               [
-                                       $name,
-                                       $thing{1}{tables}{$name}{acl},
-                                       $thing{2}{tables}{$name}{acl}
-                               ];
-                       $failcount++;
-               }
-
-       }
-
-       ## Compare sequences
-
-       ## Any sequences on 1 but not 2?
-       ## We treat the name as a unified "schema.relname"
-       SEQUENCE1:
-       for my $name (sort keys %{$thing{1}{sequences}}) {
-               next if exists $thing{2}{sequences}{$name};
-
-               ## If the schema does not exist, don't bother reporting it
-               next if ! exists $thing{2}{schemas}{ $thing{1}{sequences}{$name}{schema} };
-
-               if (exists $filter{nosequence_regex}) {
-                       for my $regex (@{$filter{nosequence_regex}}) {
-                               next SEQUENCE1 if $name =~ /$regex/;
-                       }
-               }
-
-               for my $exclude (@{$opt{exclude}}) {
-                       next SEQUENCE2 if $name =~ /$exclude/;
-               }
-
-               push @{$fail{sequences}{notexist}{1}} => $name;
-               $failcount++;
-       }
-
-       ## Any sequences on 2 but not 1?
-       SEQUENCE2:
-       for my $name (sort keys %{$thing{2}{sequences}}) {
-
-               if (exists $filter{nosequence_regex}) {
-                       for my $regex (@{$filter{nosequence_regex}}) {
-                               next SEQUENCE2 if $name =~ /$regex/;
-                       }
-               }
-
-               for my $exclude (@{$opt{exclude}}) {
-                       next SEQUENCE2 if $name =~ /$exclude/;
-               }
-
-               if (! exists $thing{1}{sequences}{$name}) {
-                       ## If the schema does not exist, don't bother reporting it
-                       if (exists $thing{1}{schemas}{ $thing{2}{sequences}{$name}{schema} }) {
-                               push @{$fail{sequences}{notexist}{2}} => $name;
-                               $failcount++;
-                       }
-                       next;
-               }
-
-               ## Do the sequences have same owner and permissions?
-               if (! exists $filter{noowners}) {
-                       if ($thing{1}{sequences}{$name}{owner} ne $thing{2}{sequences}{$name}{owner}) {
-                               push @{$fail{sequences}{diffowners}} =>
-                                       [
-                                               $name,
-                                               $thing{1}{sequences}{$name}{owner},
-                                               $thing{2}{sequences}{$name}{owner},
-                               ];
-                               $failcount++;
-                       }
-               }
-
-               if ($thing{1}{sequences}{$name}{acl} ne $thing{2}{sequences}{$name}{acl}) {
-                       push @{$fail{sequences}{diffacls}} =>
-                               [
-                                       $name,
-                                       $thing{1}{sequences}{$name}{acl},
-                                       $thing{2}{sequences}{$name}{acl}
-                               ];
-                       $failcount++;
-               }
-       }
-
-       ## Compare views
-
-       ## Any views on 1 but not 2?
-       ## We treat the name as a unified "schema.relname"
-       VIEW1:
-       for my $name (sort keys %{$thing{1}{views}}) {
-               next if exists $thing{2}{views}{$name};
-
-               ## If the schema does not exist, don't bother reporting it
-               next if ! exists $thing{2}{schemas}{ $thing{1}{views}{$name}{schema} };
-
-               if (exists $filter{noview_regex}) {
-                       for my $regex (@{$filter{noview_regex}}) {
-                               next VIEW1 if $name =~ /$regex/;
-                       }
-               }
-
-               for my $exclude (@{$opt{exclude}}) {
-                       next VIEW1 if $name =~ /$exclude/;
-               }
-
-               push @{$fail{views}{notexist}{1}} => $name;
-               $failcount++;
-       }
-
-       ## Any views on 2 but not 1?
-       VIEW2:
-       for my $name (sort keys %{$thing{2}{views}}) {
-
-               if (exists $filter{noview_regex}) {
-                       for my $regex (@{$filter{noview_regex}}) {
-                               next VIEW2 if $name =~ /$regex/;
-                       }
-               }
-
-               for my $exclude (@{$opt{exclude}}) {
-                       next VIEW2 if $name =~ /$exclude/;
-               }
-
-               if (! exists $thing{1}{views}{$name}) {
-                       ## If the schema does not exist, don't bother reporting it
-                       if (exists $thing{1}{schemas}{ $thing{2}{views}{$name}{schema} }) {
-                               push @{$fail{views}{notexist}{2}} => $name;
-                               $failcount++;
-                       }
-                       next;
-               }
-
-               ## Do the views have same owner and permissions?
-               if (! exists $filter{noowners}) {
-                       if ($thing{1}{views}{$name}{owner} ne $thing{2}{views}{$name}{owner}) {
-                               push @{$fail{views}{diffowners}} =>
-                                       [
-                                               $name,
-                                               $thing{1}{views}{$name}{owner},
-                                               $thing{2}{views}{$name}{owner},
-                               ];
-                               $failcount++;
-                       }
-               }
-
-               if ($thing{1}{views}{$name}{acl} ne $thing{2}{views}{$name}{acl}) {
-                       push @{$fail{views}{diffacls}} =>
-                               [
-                                       $name,
-                                       $thing{1}{views}{$name}{acl},
-                                       $thing{2}{views}{$name}{acl}
-                               ];
-                       $failcount++;
-               }
-
-               ## Do the views have same definitions?
-               if ($thing{1}{views}{$name}{def} ne $thing{2}{views}{$name}{def}) {
-                       push @{$fail{views}{diffdef}} => $name;
-                       $failcount++;
-               }
-
-
-       }
-
-       ## Compare triggers
-
-       ## Any triggers on 1 but not 2?
-       TRIGGER1:
-       for my $name (sort keys %{$thing{1}{triggers}}) {
-               next if exists $thing{2}{triggers}{$name};
-               if (exists $filter{notrigger_regex}) {
-                       for my $regex (@{$filter{notrigger_regex}}) {
-                               next TRIGGER1 if $name =~ /$regex/;
-                       }
-               }
-
-               for my $exclude (@{$opt{exclude}}) {
-                       next TRIGGER1 if $name =~ /$exclude/;
-               }
-
-               my $tabname = $thing{1}{triggers}{$name}->{table};
-               push @{$fail{triggers}{notexist}{1}} => [$name,$tabname];
-               $failcount++;
-       }
-
-       ## Any triggers on 2 but not 1?
-       TRIGGER2:
-       for my $name (sort keys %{$thing{2}{triggers}}) {
-               if (! exists $thing{1}{triggers}{$name}) {
-                       if (exists $filter{notrigger_regex}) {
-                               for my $regex (@{$filter{notrigger_regex}}) {
-                                       next TRIGGER2 if $name =~ /$regex/;
-                               }
-                       }
-                       my $tabname = $thing{2}{triggers}{$name}->{table};
-                       push @{$fail{triggers}{notexist}{2}} => [$name,$tabname];
-                       $failcount++;
-                       next;
-               }
-
-               for my $exclude (@{$opt{exclude}}) {
-                       next TRIGGER2 if $name =~ /$exclude/;
-               }
-
-               ## Do the triggers call the same function?
-               if (
-                       $thing{1}{triggers}{$name}{func} ne $thing{2}{triggers}{$name}{func}
-                               or $thing{1}{triggers}{$name}{args} ne $thing{2}{triggers}{$name}{args}
-               ) {
-                       push @{$fail{triggers}{difffunc}} =>
-                               [$name,
-                                $thing{1}{triggers}{$name}{func} . $thing{1}{triggers}{$name}{args},
-                                $thing{2}{triggers}{$name}{func} . $thing{2}{triggers}{$name}{args},
-                                ];
-                       $failcount++;
-               }
-       }
-
-       ## Compare columns
-
-       ## Any columns on 1 but not 2, or 2 but not 1?
-       COLUMN1:
-       for my $name (sort keys %{$thing{1}{columns}}) {
-               ## Skip any mismatched tables - already handled above
-               next if ! exists $thing{2}{columns}{$name};
-
-               for my $exclude (@{$opt{exclude}}) {
-                       next COLUMN1 if $name =~ /$exclude/;
-               }
-
-               my ($t1,$t2) = ($thing{1}{columns}{$name},$thing{2}{columns}{$name});
-               for my $col (sort keys %$t1) {
-                       if (! exists $t2->{$col}) {
-                               push @{$fail{columns}{notexist}{1}} => [$name,$col];
-                               $failcount++;
-                       }
-               }
-               for my $col (sort keys %$t2) {
-                       if (! exists $t1->{$col}) {
-                               push @{$fail{columns}{notexist}{2}} => [$name,$col];
-                               $failcount++;
-                               next;
-                       }
-                       ## They exist, so dig deeper for differences. Done in two passes.
-                       my $newtype = 0;
-                       for my $var (qw/position type default nullable/) {
-                               if ($t1->{$col}{$var} ne $t2->{$col}{$var}) {
-                                       $fail{columns}{diff}{$name}{$col}{$var} = [$t1->{$col}{$var}, $t2->{$col}{$var}];
-                                       $failcount++;
-                                       $newtype = 1 if $var eq 'type';
-                               }
-                       }
-                       ## Now the rest, with the caveat that we don't care about the rest if the type has changed
-                       if (!$newtype) {
-                               for my $var (qw/length precision scale/) {
-                                       if ($t1->{$col}{$var} ne $t2->{$col}{$var}) {
-                                               $fail{columns}{diff}{$name}{$col}{$var} = [$t1->{$col}{$var}, $t2->{$col}{$var}];
-                                               $failcount++;
-                                       }
-                               }
-                       }
-               }
-       }
-
-       ## Compare constraints
-
-       ## Table constraints - any exists on 1 but not 2?
-       CONSTRAINT1:
-       for my $name (sort keys %{$thing{1}{constraints}}) {
-               next if exists $thing{2}{constraints}{$name};
-
-               ## If the table does not exist, we don't report it
-               next if ! exists $thing{2}{tables}{ $thing{1}{constraints}{$name} };
-
-               if (exists $filter{noconstraint_regex}) {
-                       for my $regex (@{$filter{noconstraint_regex}}) {
-                               next CONSTRAINT1 if $name =~ /$regex/;
-                       }
-               }
-
-               for my $exclude (@{$opt{exclude}}) {
-                       next CONSTRAINT1 if $name =~ /$exclude/;
-               }
-
-               push @{$fail{constraints}{notexist}{1}} => [$name, $thing{1}{constraints}{$name}];
-               $failcount++;
-       }
-
-       ## Check exists on 2 but not 1, and make sure the schema/table matches
-       CONSTRAINT2:
-       for my $name (sort keys %{$thing{2}{constraints}}) {
-
-               if (exists $filter{noconstraint_regex}) {
-                       for my $regex (@{$filter{noconstraint_regex}}) {
-                               next CONSTRAINT2 if $name =~ /$regex/;
-                       }
-               }
-
-               for my $exclude (@{$opt{exclude}}) {
-                       next CONSTRAINT2 if $name =~ /$exclude/;
-               }
-
-               if (! exists $thing{1}{constraints}{$name}) {
-
-                       ## If the table does not exist, we don't report it
-                       if (exists $thing{1}{tables}{ $thing{2}{constraints}{$name} }) {
-                               push @{$fail{constraints}{notexist}{2}} => [$name, $thing{2}{constraints}{$name}];
-                               $failcount++;
-                       }
-
-                       next;
-               }
-               if ($thing{1}{constraints}{$name} ne $thing{2}{constraints}{$name}) {
-                       push @{$fail{constraints}{tablediff}} =>
-                               [
-                                       $name,
-                                       $thing{1}{constraints}{$name},
-                                       $thing{2}{constraints}{$name},
-                               ];
-                       $failcount++;
-               }
-       }
-
-       ## Column constraints - any exists on 1 but not 2?
-       CONSTRAINT3:
-       for my $name (sort keys %{$thing{1}{colconstraints}}) {
-               next if exists $thing{2}{colconstraints}{$name};
-
-               ## If the table does not exist, we don't report it
-               my ($tname,$cname) = @{$thing{1}{colconstraints}{$name}};
-               next if ! exists $thing{2}{tables}{$tname};
-
-               if (exists $filter{noconstraint_regex}) {
-                       for my $regex (@{$filter{noconstraint_regex}}) {
-                               next CONSTRAINT3 if $name =~ /$regex/;
-                       }
-               }
-
-               for my $exclude (@{$opt{exclude}}) {
-                       next CONSTRAINT3 if $name =~ /$exclude/;
-               }
-
-               push @{$fail{colconstraints}{notexist}{1}} => [$name, $tname, $cname];
-               $failcount++;
-       }
-
-       ## Check exists on 2 but not 1, and make sure the schema/table/column matches
-       CONSTRAINT4:
-       for my $name (sort keys %{$thing{2}{colconstraints}}) {
-
-               if (exists $filter{noconstraint_regex}) {
-                       for my $regex (@{$filter{noconstraint_regex}}) {
-                               next CONSTRAINT4 if $name =~ /$regex/;
-                       }
-               }
-
-               for my $exclude (@{$opt{exclude}}) {
-                       next CONSTRAINT4 if $name =~ /$exclude/;
-               }
-
-               if (! exists $thing{1}{colconstraints}{$name}) {
-
-                       ## If the table does not exist, we don't report it
-                       my ($tname,$cname) = @{$thing{2}{colconstraints}{$name}};
-                       if (exists $thing{1}{tables}{ $tname }) {
-                               push @{$fail{colconstraints}{notexist}{2}} => [$name, $tname, $cname];
-                               $failcount++;
-                       }
-                       next;
-               }
-
-               ## Check for a difference in schema/table
-               my ($tname1,$cname1,$cdef1) = @{$thing{1}{colconstraints}{$name}};
-               my ($tname2,$cname2,$cdef2) = @{$thing{2}{colconstraints}{$name}};
-               if ($tname1 ne $tname2) {
-                       push @{$fail{colconstraints}{tablediff}} =>
-                               [
-                                       $name,
-                                       $tname1,
-                                       $tname2,
-                               ];
-                       $failcount++;
-               }
-               ## Check for a difference in schema/table/column
-               elsif ($cname1 ne $cname2) {
-                       push @{$fail{colconstraints}{columndiff}} =>
-                               [
-                                       $name,
-                                       $tname1, $cname1,
-                                       $tname2, $cname2,
-                               ];
-                       $failcount++;
-               }
-               ## Check for a difference in schema/table/column/definition
-               elsif ($cdef1 ne $cdef2) {
-                       push @{$fail{colconstraints}{defdiff}} =>
-                               [
-                                       $name,
-                                       $tname1, $cname1, $cdef1,
-                                       $tname2, $cname2, $cdef2,
-                               ];
-                       $failcount++;
-               }
-       }
-
-       ## Compare languages
-       for my $name (sort keys %{$thing{1}{language}}) {
-               if (!exists $thing{2}{language}{$name}) {
-                       push @{$fail{language}{notexist}{1}} => $name;
-                       $failcount++;
-                       next;
-               }
-       }
-       for my $name (sort keys %{$thing{2}{language}}) {
-               if (!exists $thing{1}{language}{$name}) {
-                       push @{$fail{language}{notexist}{2}} => $name;
-                       $failcount++;
-                       next;
-               }
-       }
-
-       ## Compare functions
-
-       ## Functions on 1 but not 2?
-       FUNCTION1:
-       for my $name (sort keys %{$thing{1}{functions}}) {
-               next if exists $thing{2}{functions}{$name};
-
-               if (exists $filter{nofunction_regex}) {
-                       for my $regex (@{$filter{nofunction_regex}}) {
-                               next FUNCTION1 if $name =~ /$regex/;
-                       }
-               }
-
-               for my $exclude (@{$opt{exclude}}) {
-                       next FUNCTION1 if $name =~ /$exclude/;
-               }
-
-               ## Skip if these are a side effect of having a language
-               for my $l (@{$fail{language}{notexist}{1}}) {
-                       $l =~ s/u$//;
-                       next FUNCTION1 if
-                               $name eq "pg_catalog.${l}_call_handler()"
-                               or $name eq "pg_catalog.${l}_validator(oid)";
-               }
-
-               push @{$fail{functions}{notexist}{1}} => $name;
-               $failcount++;
-       }
-
-       ## Functions on 2 but not 1 and check for identity
-       FUNCTION2:
-       for my $name (sort keys %{$thing{2}{functions}}) {
-
-               if (exists $filter{nofunction_regex}) {
-                       for my $regex (@{$filter{nofunction_regex}}) {
-                               next FUNCTION2 if $name =~ /$regex/;
-                       }
-               }
-
-               for my $exclude (@{$opt{exclude}}) {
-                       next FUNCTION2 if $name =~ /$exclude/;
-               }
-
-               ## Skip if these are a side effect of having a language
-               for my $l (@{$fail{language}{notexist}{2}}) {
-                       $l =~ s/u$//;
-                       next FUNCTION2 if
-                               $name =~ "pg_catalog.${l}_call_handler()"
-                               or $name eq "pg_catalog.${l}_validator(oid)";
-               }
-
-               if (! exists $thing{1}{functions}{$name}) {
-                       push @{$fail{functions}{notexist}{2}} => $name;
-                       $failcount++;
-                       next;
-               }
-
-               ## Are the insides exactly the same
-               if (! $filter{nofuncbody}) {
-                       if ($thing{1}{functions}{$name}{md5} ne $thing{2}{functions}{$name}{md5}) {
-                               push @{$fail{functions}{diffbody}}, $name;
-                               $failcount++;
-                       }
-               }
-
-               if (! $filter{nofuncstrict}) {
-                       if ($thing{1}{functions}{$name}{isstrict} ne $thing{2}{functions}{$name}{isstrict}) {
-                               push @{$fail{functions}{diffstrict}}, $name;
-                               $failcount++;
-                       }
-               }
-
-               if (! $filter{nofuncret}) {
-                       if ($thing{1}{functions}{$name}{retset} ne $thing{2}{functions}{$name}{retset}) {
-                               push @{$fail{functions}{diffretset}}, $name;
-                               $failcount++;
-                       }
-               }
-               if (! $filter{nofuncvol}) {
-                       if ($thing{1}{functions}{$name}{volatile} ne $thing{2}{functions}{$name}{volatile}) {
-                               push @{$fail{functions}{diffvol}}, $name;
-                               $failcount++;
-                       }
-               }
-       }
-
-
-       ##
-       ## Comparison is done, let's report the results
-       ##
-
-       if (! $failcount) {
-               add_ok msg('same-matched');
-               return;
-       }
-
-       ## Build a pretty message giving all the gory details
-
-       $db->{perf} = '';
-
-       ## User differences
-       if (exists $fail{users}) {
-               if (exists $fail{users}{notexist}) {
-                       if (exists $fail{users}{notexist}{1}) {
-                               $db->{perf} .= ' Users in 1 but not 2: ';
-                               $db->{perf} .= join ', ' => @{$fail{users}{notexist}{1}};
-                               $db->{perf} .= ' ';
-                       }
-                       if (exists $fail{users}{notexist}{2}) {
-                               $db->{perf} .= ' Users in 2 but not 1: ';
-                               $db->{perf} .= join ', ' => @{$fail{users}{notexist}{2}};
-                               $db->{perf} .= ' ';
-                       }
-               }
-               if (exists $fail{users}{createdb}) {
-                       if (exists $fail{users}{createdb}{1}) {
-                               if (exists $fail{users}{createdb}{1}{t}) {
-                                       $db->{perf} .= ' Users with createdb on 1 but not 2: ';
-                                       $db->{perf} .= join ', ' => @{$fail{users}{createdb}{1}{t}};
-                                       $db->{perf} .= ' ';
-                               }
-                               if (exists $fail{users}{createdb}{1}{f}) {
-                                       $db->{perf} .= ' Users with createdb on 2 but not 1: ';
-                                       $db->{perf} .= join ', ' => @{$fail{users}{createdb}{1}{f}};
-                                       $db->{perf} .= ' ';
-                               }
-                       }
-               }
-               if (exists $fail{users}{superuser}) {
-                       if (exists $fail{users}{superuser}{1}) {
-                               if (exists $fail{users}{superuser}{1}{t}) {
-                                       $db->{perf} .= ' Users with superuser on 1 but not 2: ';
-                                       $db->{perf} .= join ', ' => @{$fail{users}{superuser}{1}{t}};
-                                       $db->{perf} .= ' ';
-                               }
-                               if (exists $fail{users}{superuser}{1}{f}) {
-                                       $db->{perf} .= ' Users with superuser on 2 but not 1: ';
-                                       $db->{perf} .= join ', ' => @{$fail{users}{superuser}{1}{f}};
-                                       $db->{perf} .= ' ';
-                               }
-                       }
-               }
-       }
-
-       ## Schema differences
-       if (exists $fail{schemas}) {
-               if (exists $fail{schemas}{notexist}) {
-                       if (exists $fail{schemas}{notexist}{1}) {
-                               for my $name (@{$fail{schemas}{notexist}{1}}) {
-                                       $db->{perf} .= " Schema in 1 but not 2: $name ";
-                               }
-                       }
-                       if (exists $fail{schemas}{notexist}{2}) {
-                               for my $name (@{$fail{schemas}{notexist}{2}}) {
-                                       $db->{perf} .= " Schema in 2 but not 1: $name ";
-                               }
-                       }
-               }
-               if (exists $fail{schemas}{diffowners}) {
-                       for my $item (@{$fail{schemas}{diffowners}}) {
-                               my ($name,$owner1,$owner2) = @$item;
-                               $db->{perf} .= qq{ Schema "$name" owned by "$owner1" on 1, but by "$owner2" on 2. };
-                       }
-               }
-               if (exists $fail{schemas}{diffacls}) {
-                       for my $item (@{$fail{schemas}{diffacls}}) {
-                               my ($name,$acl1,$acl2) = @$item;
-                               $db->{perf} .= qq{ Schema "$name" has $acl1 perms on 1, but $acl2 perms on 2. };
-                       }
-               }
-       }
-
-       ## Table differences
-       if (exists $fail{tables}) {
-               if (exists $fail{tables}{notexist}) {
-                       if (exists $fail{tables}{notexist}{1}) {
-                               for my $name (@{$fail{tables}{notexist}{1}}) {
-                                       $db->{perf} .= " Table in 1 but not 2: $name ";
-                               }
-                       }
-                       if (exists $fail{tables}{notexist}{2}) {
-                               for my $name (@{$fail{tables}{notexist}{2}}) {
-                                       $db->{perf} .= " Table in 2 but not 1: $name ";
-                               }
-                       }
-               }
-               if (exists $fail{tables}{diffowners}) {
-                       for my $item (@{$fail{tables}{diffowners}}) {
-                               my ($name,$owner1,$owner2) = @$item;
-                               $db->{perf} .= qq{ Table "$name" owned by "$owner1" on 1, but by "$owner2" on 2. };
-                       }
-               }
-               if (exists $fail{tables}{diffacls}) {
-                       for my $item (@{$fail{tables}{diffacls}}) {
-                               my ($name,$acl1,$acl2) = @$item;
-                               $db->{perf} .= qq{ Table "$name" has $acl1 perms on 1, but $acl2 perms on 2. };
-                       }
-               }
-       }
-
-       ## Sequence differences
-       if (exists $fail{sequences}) {
-               if (exists $fail{sequences}{notexist}) {
-                       if (exists $fail{sequences}{notexist}{1}) {
-                               for my $name (@{$fail{sequences}{notexist}{1}}) {
-                                       $db->{perf} .= " Sequence in 1 but not 2: $name ";
-                               }
-                       }
-                       if (exists $fail{sequences}{notexist}{2}) {
-                               for my $name (@{$fail{sequences}{notexist}{2}}) {
-                                       $db->{perf} .= " Sequence in 2 but not 1: $name ";
-                               }
-                       }
-               }
-               if (exists $fail{sequences}{diffowners}) {
-                       for my $item (@{$fail{sequences}{diffowners}}) {
-                               my ($name,$owner1,$owner2) = @$item;
-                               $db->{perf} .= qq{ Sequence "$name" owned by "$owner1" on 1, but by "$owner2" on 2. };
-                       }
-               }
-               if (exists $fail{sequences}{diffacls}) {
-                       for my $item (@{$fail{sequences}{diffacls}}) {
-                               my ($name,$acl1,$acl2) = @$item;
-                               $db->{perf} .= qq{ Sequence "$name" has $acl1 perms on 1, but $acl2 perms on 2. };
-                       }
-               }
-       }
-
-       ## View differences
-       if (exists $fail{views}) {
-               if (exists $fail{views}{notexist}) {
-                       if (exists $fail{views}{notexist}{1}) {
-                               for my $name (@{$fail{views}{notexist}{1}}) {
-                                       $db->{perf} .= " View in 1 but not 2: $name ";
-                               }
-                       }
-                       if (exists $fail{views}{notexist}{2}) {
-                               for my $name (@{$fail{views}{notexist}{2}}) {
-                                       $db->{perf} .= " View in 2 but not 1: $name ";
-                               }
-                       }
-               }
-               if (exists $fail{views}{diffowners}) {
-                       for my $item (@{$fail{views}{diffowners}}) {
-                               my ($name,$owner1,$owner2) = @$item;
-                               $db->{perf} .= qq{ View "$name" owned by "$owner1" on 1, but by "$owner2" on 2. };
-                       }
-               }
-               if (exists $fail{views}{diffacls}) {
-                       for my $item (@{$fail{views}{diffacls}}) {
-                               my ($name,$acl1,$acl2) = @$item;
-                               $db->{perf} .= qq{ View "$name" has $acl1 perms on 1, but $acl2 perms on 2. };
-                       }
-               }
-               if (exists $fail{views}{diffdef}) {
-                       for my $item (@{$fail{views}{diffdef}}) {
-                               $db->{perf} .= qq{ View "$item" is different on 1 and 2. };
-                       }
-               }
-       }
-
-       ## Trigger differences
-       if (exists $fail{triggers}) {
-               if (exists $fail{triggers}{notexist}) {
-                       if (exists $fail{triggers}{notexist}{1}) {
-                               for my $row (@{$fail{triggers}{notexist}{1}}) {
-                                       my ($name,$tabname) = @$row;
-                                       $db->{perf} .= " Trigger in 1 but not 2: $name (on $tabname) ";
-                               }
-                       }
-                       if (exists $fail{triggers}{notexist}{2}) {
-                               for my $row (@{$fail{triggers}{notexist}{2}}) {
-                                       my ($name,$tabname) = @$row;
-                                       $db->{perf} .= " Trigger in 2 but not 1: $name (on $tabname) ";
-                               }
-                       }
-               }
-               if (exists $fail{triggers}{difffunc}) {
-                       for my $item (@{$fail{triggers}{diffowners}}) {
-                               my ($name,$func1,$func2) = @$item;
-                               $db->{perf} .= qq{ Trigger "$name" calls function "$func1" on 1, but function "$func2" on 2. };
-                       }
-               }
-       }
-
-       ## Column differences
-       if (exists $fail{columns}) {
-               if (exists $fail{columns}{notexist}) {
-                       if (exists $fail{columns}{notexist}{1}) {
-                               for my $row (@{$fail{columns}{notexist}{1}}) {
-                                       my ($tname,$cname) = @$row;
-                                       $db->{perf} .= qq{ Table "$tname" on 1 has column "$cname", but 2 does not. };
-                               }
-                       }
-                       if (exists $fail{columns}{notexist}{2}) {
-                               for my $row (@{$fail{columns}{notexist}{2}}) {
-                                       my ($tname,$cname) = @$row;
-                                       $db->{perf} .= qq{ Table "$tname" on 2 has column "$cname", but 1 does not. };
-                               }
-                       }
-               }
-               if (exists $fail{columns}{diff}) {
-                       for my $tname (sort keys %{$fail{columns}{diff}}) {
-                               for my $cname (sort keys %{$fail{columns}{diff}{$tname}}) {
-                                       for my $var (sort keys %{$fail{columns}{diff}{$tname}{$cname}}) {
-                                               my ($v1,$v2) = @{$fail{columns}{diff}{$tname}{$cname}{$var}};
-                                               $db->{perf} .= qq{ Column "$cname" of "$tname": $var is $v1 on 1, but $v2 on 2. };
-                                       }
-                               }
-                       }
-               }
-       }
-
-       ## Constraint differences - table level
-       ## Don't report things twice
-       my %doublec;
-       if (exists $fail{constraints}) {
-               if (exists $fail{constraints}{notexist}) {
-                       if (exists $fail{constraints}{notexist}{1}) {
-                               for my $row (@{$fail{constraints}{notexist}{1}}) {
-                                       my ($cname,$tname) = @$row;
-                                       $db->{perf} .= qq{ Table "$tname" on 1 has constraint "$cname", but 2 does not. };
-                                       $doublec{$cname}++;
-                               }
-                       }
-                       if (exists $fail{constraints}{notexist}{2}) {
-                               for my $row (@{$fail{constraints}{notexist}{2}}) {
-                                       my ($cname,$tname) = @$row;
-                                       $db->{perf} .= qq{ Table "$tname" on 2 has constraint "$cname", but 1 does not. };
-                                       $doublec{$cname}++;
-                               }
-                       }
-               }
-               if (exists $fail{constraints}{tablediff}) {
-                       for my $row (@{$fail{constraints}{tablediff}}) {
-                               my ($cname,$t1,$t2) = @$row;
-                               $db->{perf} .= qq{ Constraint "$cname" is applied to "$t1" on 1, but to "$t2" on 2. };
-                               $doublec{$cname}++;
-                       }
-               }
-       }
-
-       ## Constraint differences - column level
-       if (exists $fail{colconstraints}) {
-               if (exists $fail{colconstraints}{notexist}) {
-                       if (exists $fail{colconstraints}{notexist}{1}) {
-                               for my $row (@{$fail{colconstraints}{notexist}{1}}) {
-                                       my ($name,$tname,$cname) = @$row;
-                                       if (! exists $doublec{$name}) {
-                                               $db->{perf} .= qq{ Table "$tname" on 1 has constraint "$name" on column "$cname", but 2 does not. };
-                                       }
-                                       else {
-                                               $failcount--;
-                                       }
-                               }
-                       }
-                       if (exists $fail{colconstraints}{notexist}{2}) {
-                               for my $row (@{$fail{colconstraints}{notexist}{2}}) {
-                                       my ($name,$tname,$cname) = @$row;
-                                       if (! exists $doublec{$name}) {
-                                               $db->{perf} .= qq{ Table "$tname" on 2 has constraint "$name" on column "$cname", but 1 does not. };
-                                       }
-                                       else {
-                                               $failcount--;
-                                       }
-                               }
-                       }
-               }
-               if (exists $fail{colconstraints}{tablediff}) {
-                       for my $row (@{$fail{colconstraints}{tablediff}}) {
-                               my ($name,$t1,$t2) = @$row;
-                               if (! exists $doublec{$name}) {
-                                       $db->{perf} .= qq{ Constraint "$name" is applied to "$t1" on 1, but to "$t2" on 2. };
-                               }
-                               else {
-                                       $failcount--;
-                               }
-                       }
-               }
-               if (exists $fail{colconstraints}{columndiff}) {
-                       for my $row (@{$fail{colconstraints}{columndiff}}) {
-                               my ($name,$t1,$c1,$t2,$c2) = @$row;
-                               if (! exists $doublec{$name}) {
-                                       $db->{perf} .= qq{ Constraint "$name" on 1 is applied to $t1.$c1, but to $t2.$c2 on 2. };
-                               }
-                               else {
-                                       $failcount--;
-                               }
-                       }
-               }
-               if (exists $fail{colconstraints}{defdiff}) {
-                       for my $row (@{$fail{colconstraints}{defdiff}}) {
-                               my ($name,$t1,$c1,$d1,$t2,$c2,$d2) = @$row;
-                               if (! exists $doublec{$name}) {
-                                       $db->{perf} .= qq{ Constraint "$name" on 1 differs from 2 ("$d1" vs. "$d2") };
-                               }
-                               else {
-                                       $failcount--;
-                               }
-                       }
-               }
-       }
-
-       ## Function differences
-       if (exists $fail{functions}) {
-               if (exists $fail{functions}{notexist}) {
-                       if (exists $fail{functions}{notexist}{1}) {
-                               for my $name (@{$fail{functions}{notexist}{1}}) {
-                                       $db->{perf} .= " Function on 1 but not 2: $name ";
-                               }
-                       }
-                       if (exists $fail{functions}{notexist}{2}) {
-                               for my $name (@{$fail{functions}{notexist}{2}}) {
-                                       $db->{perf} .= " Function on 2 but not 1: $name ";
-                               }
-                       }
-               }
-               if (exists $fail{functions}{diffbody}) {
-                       for my $name (sort @{$fail{functions}{diffbody}}) {
-                               $db->{perf} .= " Function body different on 1 than 2: $name ";
-                       }
-               }
-               if (exists $fail{functions}{diffstrict}) {
-                       for my $name (sort @{$fail{functions}{diffbody}}) {
-                               $db->{perf} .= " Function strictness different on 1 than 2: $name ";
-                       }
-               }
-               if (exists $fail{functions}{diffretset}) {
-                       for my $name (sort @{$fail{functions}{diffretset}}) {
-                               $db->{perf} .= " Function return-set different on 1 than 2: $name ";
-                       }
-               }
-               if (exists $fail{functions}{diffvol}) {
-                       for my $name (sort @{$fail{functions}{diffvol}}) {
-                               $db->{perf} .= " Function volatilitiy different on 1 than 2: $name ";
-                       }
-               }
-       }
-
-       ## Language differences
-       if (exists $fail{language}) {
-               if (exists $fail{language}{notexist}) {
-                       if (exists $fail{language}{notexist}{1}) {
-                               for my $name (@{$fail{language}{notexist}{1}}) {
-                                       $db->{perf} .= " Language on 1 but not 2: $name ";
-                               }
-                       }
-                       if (exists $fail{language}{notexist}{2}) {
-                               for my $name (@{$fail{language}{notexist}{2}}) {
-                                       $db->{perf} .= " Language on 2 but not 1: $name ";
-                               }
-                       }
-               }
-       }
-
-
-       add_critical msg('same-failed', $failcount);
-
-       return;
+            $info = run_command($SQL, { dbuser => $opt{dbuser}[$x-1], dbnumber => $x } );
+            for $db (@{$info->{db}}) {
+                for my $r (@{$db->{slurp}}) {
+                    my ($schema,$name,$args,$md5,$isstrict,$retset,$volatile) = @$r{
+                        qw/ nspname proname proargtypes md proisstrict proretset provolatile /};
+                    $args =~ s/ /,/g;
+                    $args =~ s/(\d+)/$thing{$x}{type}{$1}/g;
+                    $args =~ s/^\s*(.*)\s*$/($1)/;
+                    $thing{$x}{functions}{"${schema}.${name}${args}"} = {
+                        md5 => $md5,
+                        isstrict => $isstrict,
+                        retset => $retset,
+                        volatile => $volatile,
+                    };
+                }
+            }
+        }
+
+        ## Get a list of all languages
+        if (! exists $filter{nolanguages}) {
+            $SQL = q{SELECT lanname FROM pg_language};
+            $info = run_command($SQL, { dbuser => $opt{dbuser}[$x-1], dbnumber => $x } );
+            for $db (@{$info->{db}}) {
+                for my $r (@{$db->{slurp}}) {
+                    $thing{$x}{language}{$r->{lanname}} = 1;
+                }
+            }
+        }
+
+
+    } ## end each database to query
+
+    $db = $saved_db;
+
+    ## Build a list of what has failed
+    my %fail;
+    my $failcount = 0;
+
+    ## Compare users
+
+    ## Any users on 1 but not 2?
+    USER1:
+    for my $user (sort keys %{$thing{1}{users}}) {
+        next if exists $thing{2}{users}{$user};
+
+        if (exists $filter{nouser_regex}) {
+            for my $regex (@{$filter{nouser_regex}}) {
+                next USER1 if $user =~ /$regex/;
+            }
+        }
+
+        push @{$fail{users}{notexist}{1}} => $user;
+        $failcount++;
+    }
+
+    ## Any users on 2 but not 1?
+    USER2:
+    for my $user (sort keys %{$thing{2}{users}}) {
+
+        if (exists $filter{nouser_regex}) {
+            for my $regex (@{$filter{nouser_regex}}) {
+                next USER2 if $user =~ /$regex/;
+            }
+        }
+
+        if (! exists $thing{1}{users}{$user}) {
+            push @{$fail{users}{notexist}{2}} => $user;
+            $failcount++;
+            next;
+        }
+        ## Do the matching users have the same superpowers?
+
+        if ($thing{1}{users}{$user}{createdb} ne $thing{2}{users}{$user}{createdb}) {
+            push @{$fail{users}{createdb}{1}{$thing{1}{users}{$user}{createdb}}} => $user;
+            $failcount++;
+        }
+
+        if ($thing{1}{users}{$user}{superuser} ne $thing{2}{users}{$user}{superuser}) {
+            push @{$fail{users}{superuser}{1}{$thing{1}{users}{$user}{superuser}}} => $user;
+            $failcount++;
+        }
+    }
+
+    ## Compare schemas
+
+    ## Any schemas on 1 but not 2?
+    SCHEMA1:
+    for my $name (sort keys %{$thing{1}{schemas}}) {
+        next if exists $thing{2}{schemas}{$name};
+
+        if (exists $filter{noschema_regex}) {
+            for my $regex (@{$filter{noschema_regex}}) {
+                next SCHEMA1 if $name =~ /$regex/;
+            }
+        }
+
+        push @{$fail{schemas}{notexist}{1}} => $name;
+        $failcount++;
+    }
+
+    ## Any schemas on 2 but not 1?
+    SCHEMA2:
+    for my $name (sort keys %{$thing{2}{schemas}}) {
+
+        if (exists $filter{noschema_regex}) {
+            for my $regex (@{$filter{noschema_regex}}) {
+                next SCHEMA2 if $name =~ /$regex/;
+            }
+        }
+
+        if (! exists $thing{1}{schemas}{$name}) {
+            push @{$fail{schemas}{notexist}{2}} => $name;
+            $failcount++;
+            next;
+        }
+
+        ## Do the schemas have same owner and permissions?
+        if (! exists $filter{noowners}) {
+            if ($thing{1}{schemas}{$name}{owner} ne $thing{2}{schemas}{$name}{owner}) {
+                push @{$fail{schemas}{diffowners}} =>
+                    [
+                        $name,
+                        $thing{1}{schemas}{$name}{owner},
+                        $thing{2}{schemas}{$name}{owner},
+                ];
+                $failcount++;
+            }
+        }
+
+        if ($thing{1}{schemas}{$name}{acl} ne $thing{2}{schemas}{$name}{acl}) {
+            push @{$fail{schemas}{diffacls}} =>
+                [
+                    $name,
+                    $thing{1}{schemas}{$name}{acl},
+                    $thing{2}{schemas}{$name}{acl},
+                ];
+            $failcount++;
+        }
+
+    }
+
+    ## Compare tables
+
+    ## Any tables on 1 but not 2?
+    ## We treat the name as a unified "schema.relname"
+    TABLE1:
+    for my $name (sort keys %{$thing{1}{tables}}) {
+        next if exists $thing{2}{tables}{$name};
+
+        ## If the schema does not exist, don't bother reporting it
+        next if ! exists $thing{2}{schemas}{ $thing{1}{tables}{$name}{schema} };
+
+        if (exists $filter{notable_regex}) {
+            for my $regex (@{$filter{notable_regex}}) {
+                next TABLE1 if $name =~ /$regex/;
+            }
+        }
+
+        for my $exclude (@{$opt{exclude}}) {
+            next TABLE1 if $name =~ /$exclude/;
+        }
+
+        push @{$fail{tables}{notexist}{1}} => $name;
+        $failcount++;
+    }
+
+    ## Any tables on 2 but not 1?
+    TABLE2:
+    for my $name (sort keys %{$thing{2}{tables}}) {
+
+        if (exists $filter{notable_regex}) {
+            for my $regex (@{$filter{notable_regex}}) {
+                next TABLE2 if $name =~ /$regex/;
+            }
+        }
+
+        for my $exclude (@{$opt{exclude}}) {
+            next TABLE2 if $name =~ /$exclude/;
+        }
+
+        if (! exists $thing{1}{tables}{$name}) {
+            ## If the schema does not exist, don't bother reporting it
+            if (exists $thing{1}{schemas}{ $thing{2}{tables}{$name}{schema} }) {
+                push @{$fail{tables}{notexist}{2}} => $name;
+                $failcount++;
+            }
+            next;
+        }
+
+        ## Do the tables have same owner and permissions?
+        if (! exists $filter{noowners}) {
+            if ($thing{1}{tables}{$name}{owner} ne $thing{2}{tables}{$name}{owner}) {
+                push @{$fail{tables}{diffowners}} =>
+                    [
+                        $name,
+                        $thing{1}{tables}{$name}{owner},
+                        $thing{2}{tables}{$name}{owner},
+                ];
+                $failcount++;
+            }
+        }
+
+        if ($thing{1}{tables}{$name}{acl} ne $thing{2}{tables}{$name}{acl}) {
+            push @{$fail{tables}{diffacls}} =>
+                [
+                    $name,
+                    $thing{1}{tables}{$name}{acl},
+                    $thing{2}{tables}{$name}{acl}
+                ];
+            $failcount++;
+        }
+
+    }
+
+    ## Compare sequences
+
+    ## Any sequences on 1 but not 2?
+    ## We treat the name as a unified "schema.relname"
+    SEQUENCE1:
+    for my $name (sort keys %{$thing{1}{sequences}}) {
+        next if exists $thing{2}{sequences}{$name};
+
+        ## If the schema does not exist, don't bother reporting it
+        next if ! exists $thing{2}{schemas}{ $thing{1}{sequences}{$name}{schema} };
+
+        if (exists $filter{nosequence_regex}) {
+            for my $regex (@{$filter{nosequence_regex}}) {
+                next SEQUENCE1 if $name =~ /$regex/;
+            }
+        }
+
+        for my $exclude (@{$opt{exclude}}) {
+            next SEQUENCE2 if $name =~ /$exclude/;
+        }
+
+        push @{$fail{sequences}{notexist}{1}} => $name;
+        $failcount++;
+    }
+
+    ## Any sequences on 2 but not 1?
+    SEQUENCE2:
+    for my $name (sort keys %{$thing{2}{sequences}}) {
+
+        if (exists $filter{nosequence_regex}) {
+            for my $regex (@{$filter{nosequence_regex}}) {
+                next SEQUENCE2 if $name =~ /$regex/;
+            }
+        }
+
+        for my $exclude (@{$opt{exclude}}) {
+            next SEQUENCE2 if $name =~ /$exclude/;
+        }
+
+        if (! exists $thing{1}{sequences}{$name}) {
+            ## If the schema does not exist, don't bother reporting it
+            if (exists $thing{1}{schemas}{ $thing{2}{sequences}{$name}{schema} }) {
+                push @{$fail{sequences}{notexist}{2}} => $name;
+                $failcount++;
+            }
+            next;
+        }
+
+        ## Do the sequences have same owner and permissions?
+        if (! exists $filter{noowners}) {
+            if ($thing{1}{sequences}{$name}{owner} ne $thing{2}{sequences}{$name}{owner}) {
+                push @{$fail{sequences}{diffowners}} =>
+                    [
+                        $name,
+                        $thing{1}{sequences}{$name}{owner},
+                        $thing{2}{sequences}{$name}{owner},
+                ];
+                $failcount++;
+            }
+        }
+
+        if ($thing{1}{sequences}{$name}{acl} ne $thing{2}{sequences}{$name}{acl}) {
+            push @{$fail{sequences}{diffacls}} =>
+                [
+                    $name,
+                    $thing{1}{sequences}{$name}{acl},
+                    $thing{2}{sequences}{$name}{acl}
+                ];
+            $failcount++;
+        }
+    }
+
+    ## Compare views
+
+    ## Any views on 1 but not 2?
+    ## We treat the name as a unified "schema.relname"
+    VIEW1:
+    for my $name (sort keys %{$thing{1}{views}}) {
+        next if exists $thing{2}{views}{$name};
+
+        ## If the schema does not exist, don't bother reporting it
+        next if ! exists $thing{2}{schemas}{ $thing{1}{views}{$name}{schema} };
+
+        if (exists $filter{noview_regex}) {
+            for my $regex (@{$filter{noview_regex}}) {
+                next VIEW1 if $name =~ /$regex/;
+            }
+        }
+
+        for my $exclude (@{$opt{exclude}}) {
+            next VIEW1 if $name =~ /$exclude/;
+        }
+
+        push @{$fail{views}{notexist}{1}} => $name;
+        $failcount++;
+    }
+
+    ## Any views on 2 but not 1?
+    VIEW2:
+    for my $name (sort keys %{$thing{2}{views}}) {
+
+        if (exists $filter{noview_regex}) {
+            for my $regex (@{$filter{noview_regex}}) {
+                next VIEW2 if $name =~ /$regex/;
+            }
+        }
+
+        for my $exclude (@{$opt{exclude}}) {
+            next VIEW2 if $name =~ /$exclude/;
+        }
+
+        if (! exists $thing{1}{views}{$name}) {
+            ## If the schema does not exist, don't bother reporting it
+            if (exists $thing{1}{schemas}{ $thing{2}{views}{$name}{schema} }) {
+                push @{$fail{views}{notexist}{2}} => $name;
+                $failcount++;
+            }
+            next;
+        }
+
+        ## Do the views have same owner and permissions?
+        if (! exists $filter{noowners}) {
+            if ($thing{1}{views}{$name}{owner} ne $thing{2}{views}{$name}{owner}) {
+                push @{$fail{views}{diffowners}} =>
+                    [
+                        $name,
+                        $thing{1}{views}{$name}{owner},
+                        $thing{2}{views}{$name}{owner},
+                ];
+                $failcount++;
+            }
+        }
+
+        if ($thing{1}{views}{$name}{acl} ne $thing{2}{views}{$name}{acl}) {
+            push @{$fail{views}{diffacls}} =>
+                [
+                    $name,
+                    $thing{1}{views}{$name}{acl},
+                    $thing{2}{views}{$name}{acl}
+                ];
+            $failcount++;
+        }
+
+        ## Do the views have same definitions?
+        if ($thing{1}{views}{$name}{def} ne $thing{2}{views}{$name}{def}) {
+            push @{$fail{views}{diffdef}} => $name;
+            $failcount++;
+        }
+
+
+    }
+
+    ## Compare triggers
+
+    ## Any triggers on 1 but not 2?
+    TRIGGER1:
+    for my $name (sort keys %{$thing{1}{triggers}}) {
+        next if exists $thing{2}{triggers}{$name};
+        if (exists $filter{notrigger_regex}) {
+            for my $regex (@{$filter{notrigger_regex}}) {
+                next TRIGGER1 if $name =~ /$regex/;
+            }
+        }
+
+        for my $exclude (@{$opt{exclude}}) {
+            next TRIGGER1 if $name =~ /$exclude/;
+        }
+
+        my $tabname = $thing{1}{triggers}{$name}->{table};
+        push @{$fail{triggers}{notexist}{1}} => [$name,$tabname];
+        $failcount++;
+    }
+
+    ## Any triggers on 2 but not 1?
+    TRIGGER2:
+    for my $name (sort keys %{$thing{2}{triggers}}) {
+        if (! exists $thing{1}{triggers}{$name}) {
+            if (exists $filter{notrigger_regex}) {
+                for my $regex (@{$filter{notrigger_regex}}) {
+                    next TRIGGER2 if $name =~ /$regex/;
+                }
+            }
+            my $tabname = $thing{2}{triggers}{$name}->{table};
+            push @{$fail{triggers}{notexist}{2}} => [$name,$tabname];
+            $failcount++;
+            next;
+        }
+
+        for my $exclude (@{$opt{exclude}}) {
+            next TRIGGER2 if $name =~ /$exclude/;
+        }
+
+        ## Do the triggers call the same function?
+        if (
+            $thing{1}{triggers}{$name}{func} ne $thing{2}{triggers}{$name}{func}
+                or $thing{1}{triggers}{$name}{args} ne $thing{2}{triggers}{$name}{args}
+        ) {
+            push @{$fail{triggers}{difffunc}} =>
+                [$name,
+                 $thing{1}{triggers}{$name}{func} . $thing{1}{triggers}{$name}{args},
+                 $thing{2}{triggers}{$name}{func} . $thing{2}{triggers}{$name}{args},
+                 ];
+            $failcount++;
+        }
+    }
+
+    ## Compare columns
+
+    ## Any columns on 1 but not 2, or 2 but not 1?
+    COLUMN1:
+    for my $name (sort keys %{$thing{1}{columns}}) {
+        ## Skip any mismatched tables - already handled above
+        next if ! exists $thing{2}{columns}{$name};
+
+        for my $exclude (@{$opt{exclude}}) {
+            next COLUMN1 if $name =~ /$exclude/;
+        }
+
+        my ($t1,$t2) = ($thing{1}{columns}{$name},$thing{2}{columns}{$name});
+        for my $col (sort keys %$t1) {
+            if (! exists $t2->{$col}) {
+                push @{$fail{columns}{notexist}{1}} => [$name,$col];
+                $failcount++;
+            }
+        }
+        for my $col (sort keys %$t2) {
+            if (! exists $t1->{$col}) {
+                push @{$fail{columns}{notexist}{2}} => [$name,$col];
+                $failcount++;
+                next;
+            }
+            ## They exist, so dig deeper for differences. Done in two passes.
+            my $newtype = 0;
+            for my $var (qw/position type default nullable/) {
+                if ($t1->{$col}{$var} ne $t2->{$col}{$var}) {
+                    $fail{columns}{diff}{$name}{$col}{$var} = [$t1->{$col}{$var}, $t2->{$col}{$var}];
+                    $failcount++;
+                    $newtype = 1 if $var eq 'type';
+                }
+            }
+            ## Now the rest, with the caveat that we don't care about the rest if the type has changed
+            if (!$newtype) {
+                for my $var (qw/length precision scale/) {
+                    if ($t1->{$col}{$var} ne $t2->{$col}{$var}) {
+                        $fail{columns}{diff}{$name}{$col}{$var} = [$t1->{$col}{$var}, $t2->{$col}{$var}];
+                        $failcount++;
+                    }
+                }
+            }
+        }
+    }
+
+    ## Compare constraints
+
+    ## Table constraints - any exists on 1 but not 2?
+    CONSTRAINT1:
+    for my $name (sort keys %{$thing{1}{constraints}}) {
+        next if exists $thing{2}{constraints}{$name};
+
+        ## If the table does not exist, we don't report it
+        next if ! exists $thing{2}{tables}{ $thing{1}{constraints}{$name} };
+
+        if (exists $filter{noconstraint_regex}) {
+            for my $regex (@{$filter{noconstraint_regex}}) {
+                next CONSTRAINT1 if $name =~ /$regex/;
+            }
+        }
+
+        for my $exclude (@{$opt{exclude}}) {
+            next CONSTRAINT1 if $name =~ /$exclude/;
+        }
+
+        push @{$fail{constraints}{notexist}{1}} => [$name, $thing{1}{constraints}{$name}];
+        $failcount++;
+    }
+
+    ## Check exists on 2 but not 1, and make sure the schema/table matches
+    CONSTRAINT2:
+    for my $name (sort keys %{$thing{2}{constraints}}) {
+
+        if (exists $filter{noconstraint_regex}) {
+            for my $regex (@{$filter{noconstraint_regex}}) {
+                next CONSTRAINT2 if $name =~ /$regex/;
+            }
+        }
+
+        for my $exclude (@{$opt{exclude}}) {
+            next CONSTRAINT2 if $name =~ /$exclude/;
+        }
+
+        if (! exists $thing{1}{constraints}{$name}) {
+
+            ## If the table does not exist, we don't report it
+            if (exists $thing{1}{tables}{ $thing{2}{constraints}{$name} }) {
+                push @{$fail{constraints}{notexist}{2}} => [$name, $thing{2}{constraints}{$name}];
+                $failcount++;
+            }
+
+            next;
+        }
+        if ($thing{1}{constraints}{$name} ne $thing{2}{constraints}{$name}) {
+            push @{$fail{constraints}{tablediff}} =>
+                [
+                    $name,
+                    $thing{1}{constraints}{$name},
+                    $thing{2}{constraints}{$name},
+                ];
+            $failcount++;
+        }
+    }
+
+    ## Column constraints - any exists on 1 but not 2?
+    CONSTRAINT3:
+    for my $name (sort keys %{$thing{1}{colconstraints}}) {
+        next if exists $thing{2}{colconstraints}{$name};
+
+        ## If the table does not exist, we don't report it
+        my ($tname,$cname) = @{$thing{1}{colconstraints}{$name}};
+        next if ! exists $thing{2}{tables}{$tname};
+
+        if (exists $filter{noconstraint_regex}) {
+            for my $regex (@{$filter{noconstraint_regex}}) {
+                next CONSTRAINT3 if $name =~ /$regex/;
+            }
+        }
+
+        for my $exclude (@{$opt{exclude}}) {
+            next CONSTRAINT3 if $name =~ /$exclude/;
+        }
+
+        push @{$fail{colconstraints}{notexist}{1}} => [$name, $tname, $cname];
+        $failcount++;
+    }
+
+    ## Check exists on 2 but not 1, and make sure the schema/table/column matches
+    CONSTRAINT4:
+    for my $name (sort keys %{$thing{2}{colconstraints}}) {
+
+        if (exists $filter{noconstraint_regex}) {
+            for my $regex (@{$filter{noconstraint_regex}}) {
+                next CONSTRAINT4 if $name =~ /$regex/;
+            }
+        }
+
+        for my $exclude (@{$opt{exclude}}) {
+            next CONSTRAINT4 if $name =~ /$exclude/;
+        }
+
+        if (! exists $thing{1}{colconstraints}{$name}) {
+
+            ## If the table does not exist, we don't report it
+            my ($tname,$cname) = @{$thing{2}{colconstraints}{$name}};
+            if (exists $thing{1}{tables}{ $tname }) {
+                push @{$fail{colconstraints}{notexist}{2}} => [$name, $tname, $cname];
+                $failcount++;
+            }
+            next;
+        }
+
+        ## Check for a difference in schema/table
+        my ($tname1,$cname1,$cdef1) = @{$thing{1}{colconstraints}{$name}};
+        my ($tname2,$cname2,$cdef2) = @{$thing{2}{colconstraints}{$name}};
+        if ($tname1 ne $tname2) {
+            push @{$fail{colconstraints}{tablediff}} =>
+                [
+                    $name,
+                    $tname1,
+                    $tname2,
+                ];
+            $failcount++;
+        }
+        ## Check for a difference in schema/table/column
+        elsif ($cname1 ne $cname2) {
+            push @{$fail{colconstraints}{columndiff}} =>
+                [
+                    $name,
+                    $tname1, $cname1,
+                    $tname2, $cname2,
+                ];
+            $failcount++;
+        }
+        ## Check for a difference in schema/table/column/definition
+        elsif ($cdef1 ne $cdef2) {
+            push @{$fail{colconstraints}{defdiff}} =>
+                [
+                    $name,
+                    $tname1, $cname1, $cdef1,
+                    $tname2, $cname2, $cdef2,
+                ];
+            $failcount++;
+        }
+    }
+
+    ## Compare languages
+    for my $name (sort keys %{$thing{1}{language}}) {
+        if (!exists $thing{2}{language}{$name}) {
+            push @{$fail{language}{notexist}{1}} => $name;
+            $failcount++;
+            next;
+        }
+    }
+    for my $name (sort keys %{$thing{2}{language}}) {
+        if (!exists $thing{1}{language}{$name}) {
+            push @{$fail{language}{notexist}{2}} => $name;
+            $failcount++;
+            next;
+        }
+    }
+
+    ## Compare functions
+
+    ## Functions on 1 but not 2?
+    FUNCTION1:
+    for my $name (sort keys %{$thing{1}{functions}}) {
+        next if exists $thing{2}{functions}{$name};
+
+        if (exists $filter{nofunction_regex}) {
+            for my $regex (@{$filter{nofunction_regex}}) {
+                next FUNCTION1 if $name =~ /$regex/;
+            }
+        }
+
+        for my $exclude (@{$opt{exclude}}) {
+            next FUNCTION1 if $name =~ /$exclude/;
+        }
+
+        ## Skip if these are a side effect of having a language
+        for my $l (@{$fail{language}{notexist}{1}}) {
+            $l =~ s/u$//;
+            next FUNCTION1 if
+                $name eq "pg_catalog.${l}_call_handler()"
+                or $name eq "pg_catalog.${l}_validator(oid)";
+        }
+
+        push @{$fail{functions}{notexist}{1}} => $name;
+        $failcount++;
+    }
+
+    ## Functions on 2 but not 1 and check for identity
+    FUNCTION2:
+    for my $name (sort keys %{$thing{2}{functions}}) {
+
+        if (exists $filter{nofunction_regex}) {
+            for my $regex (@{$filter{nofunction_regex}}) {
+                next FUNCTION2 if $name =~ /$regex/;
+            }
+        }
+
+        for my $exclude (@{$opt{exclude}}) {
+            next FUNCTION2 if $name =~ /$exclude/;
+        }
+
+        ## Skip if these are a side effect of having a language
+        for my $l (@{$fail{language}{notexist}{2}}) {
+            $l =~ s/u$//;
+            next FUNCTION2 if
+                $name =~ "pg_catalog.${l}_call_handler()"
+                or $name eq "pg_catalog.${l}_validator(oid)";
+        }
+
+        if (! exists $thing{1}{functions}{$name}) {
+            push @{$fail{functions}{notexist}{2}} => $name;
+            $failcount++;
+            next;
+        }
+
+        ## Are the insides exactly the same
+        if (! $filter{nofuncbody}) {
+            if ($thing{1}{functions}{$name}{md5} ne $thing{2}{functions}{$name}{md5}) {
+                push @{$fail{functions}{diffbody}}, $name;
+                $failcount++;
+            }
+        }
+
+        if (! $filter{nofuncstrict}) {
+            if ($thing{1}{functions}{$name}{isstrict} ne $thing{2}{functions}{$name}{isstrict}) {
+                push @{$fail{functions}{diffstrict}}, $name;
+                $failcount++;
+            }
+        }
+
+        if (! $filter{nofuncret}) {
+            if ($thing{1}{functions}{$name}{retset} ne $thing{2}{functions}{$name}{retset}) {
+                push @{$fail{functions}{diffretset}}, $name;
+                $failcount++;
+            }
+        }
+        if (! $filter{nofuncvol}) {
+            if ($thing{1}{functions}{$name}{volatile} ne $thing{2}{functions}{$name}{volatile}) {
+                push @{$fail{functions}{diffvol}}, $name;
+                $failcount++;
+            }
+        }
+    }
+
+
+    ##
+    ## Comparison is done, let's report the results
+    ##
+
+    if (! $failcount) {
+        add_ok msg('same-matched');
+        return;
+    }
+
+    ## Build a pretty message giving all the gory details
+
+    $db->{perf} = '';
+
+    ## User differences
+    if (exists $fail{users}) {
+        if (exists $fail{users}{notexist}) {
+            if (exists $fail{users}{notexist}{1}) {
+                $db->{perf} .= ' Users in 1 but not 2: ';
+                $db->{perf} .= join ', ' => @{$fail{users}{notexist}{1}};
+                $db->{perf} .= ' ';
+            }
+            if (exists $fail{users}{notexist}{2}) {
+                $db->{perf} .= ' Users in 2 but not 1: ';
+                $db->{perf} .= join ', ' => @{$fail{users}{notexist}{2}};
+                $db->{perf} .= ' ';
+            }
+        }
+        if (exists $fail{users}{createdb}) {
+            if (exists $fail{users}{createdb}{1}) {
+                if (exists $fail{users}{createdb}{1}{t}) {
+                    $db->{perf} .= ' Users with createdb on 1 but not 2: ';
+                    $db->{perf} .= join ', ' => @{$fail{users}{createdb}{1}{t}};
+                    $db->{perf} .= ' ';
+                }
+                if (exists $fail{users}{createdb}{1}{f}) {
+                    $db->{perf} .= ' Users with createdb on 2 but not 1: ';
+                    $db->{perf} .= join ', ' => @{$fail{users}{createdb}{1}{f}};
+                    $db->{perf} .= ' ';
+                }
+            }
+        }
+        if (exists $fail{users}{superuser}) {
+            if (exists $fail{users}{superuser}{1}) {
+                if (exists $fail{users}{superuser}{1}{t}) {
+                    $db->{perf} .= ' Users with superuser on 1 but not 2: ';
+                    $db->{perf} .= join ', ' => @{$fail{users}{superuser}{1}{t}};
+                    $db->{perf} .= ' ';
+                }
+                if (exists $fail{users}{superuser}{1}{f}) {
+                    $db->{perf} .= ' Users with superuser on 2 but not 1: ';
+                    $db->{perf} .= join ', ' => @{$fail{users}{superuser}{1}{f}};
+                    $db->{perf} .= ' ';
+                }
+            }
+        }
+    }
+
+    ## Schema differences
+    if (exists $fail{schemas}) {
+        if (exists $fail{schemas}{notexist}) {
+            if (exists $fail{schemas}{notexist}{1}) {
+                for my $name (@{$fail{schemas}{notexist}{1}}) {
+                    $db->{perf} .= " Schema in 1 but not 2: $name ";
+                }
+            }
+            if (exists $fail{schemas}{notexist}{2}) {
+                for my $name (@{$fail{schemas}{notexist}{2}}) {
+                    $db->{perf} .= " Schema in 2 but not 1: $name ";
+                }
+            }
+        }
+        if (exists $fail{schemas}{diffowners}) {
+            for my $item (@{$fail{schemas}{diffowners}}) {
+                my ($name,$owner1,$owner2) = @$item;
+                $db->{perf} .= qq{ Schema "$name" owned by "$owner1" on 1, but by "$owner2" on 2. };
+            }
+        }
+        if (exists $fail{schemas}{diffacls}) {
+            for my $item (@{$fail{schemas}{diffacls}}) {
+                my ($name,$acl1,$acl2) = @$item;
+                $db->{perf} .= qq{ Schema "$name" has $acl1 perms on 1, but $acl2 perms on 2. };
+            }
+        }
+    }
+
+    ## Table differences
+    if (exists $fail{tables}) {
+        if (exists $fail{tables}{notexist}) {
+            if (exists $fail{tables}{notexist}{1}) {
+                for my $name (@{$fail{tables}{notexist}{1}}) {
+                    $db->{perf} .= " Table in 1 but not 2: $name ";
+                }
+            }
+            if (exists $fail{tables}{notexist}{2}) {
+                for my $name (@{$fail{tables}{notexist}{2}}) {
+                    $db->{perf} .= " Table in 2 but not 1: $name ";
+                }
+            }
+        }
+        if (exists $fail{tables}{diffowners}) {
+            for my $item (@{$fail{tables}{diffowners}}) {
+                my ($name,$owner1,$owner2) = @$item;
+                $db->{perf} .= qq{ Table "$name" owned by "$owner1" on 1, but by "$owner2" on 2. };
+            }
+        }
+        if (exists $fail{tables}{diffacls}) {
+            for my $item (@{$fail{tables}{diffacls}}) {
+                my ($name,$acl1,$acl2) = @$item;
+                $db->{perf} .= qq{ Table "$name" has $acl1 perms on 1, but $acl2 perms on 2. };
+            }
+        }
+    }
+
+    ## Sequence differences
+    if (exists $fail{sequences}) {
+        if (exists $fail{sequences}{notexist}) {
+            if (exists $fail{sequences}{notexist}{1}) {
+                for my $name (@{$fail{sequences}{notexist}{1}}) {
+                    $db->{perf} .= " Sequence in 1 but not 2: $name ";
+                }
+            }
+            if (exists $fail{sequences}{notexist}{2}) {
+                for my $name (@{$fail{sequences}{notexist}{2}}) {
+                    $db->{perf} .= " Sequence in 2 but not 1: $name ";
+                }
+            }
+        }
+        if (exists $fail{sequences}{diffowners}) {
+            for my $item (@{$fail{sequences}{diffowners}}) {
+                my ($name,$owner1,$owner2) = @$item;
+                $db->{perf} .= qq{ Sequence "$name" owned by "$owner1" on 1, but by "$owner2" on 2. };
+            }
+        }
+        if (exists $fail{sequences}{diffacls}) {
+            for my $item (@{$fail{sequences}{diffacls}}) {
+                my ($name,$acl1,$acl2) = @$item;
+                $db->{perf} .= qq{ Sequence "$name" has $acl1 perms on 1, but $acl2 perms on 2. };
+            }
+        }
+    }
+
+    ## View differences
+    if (exists $fail{views}) {
+        if (exists $fail{views}{notexist}) {
+            if (exists $fail{views}{notexist}{1}) {
+                for my $name (@{$fail{views}{notexist}{1}}) {
+                    $db->{perf} .= " View in 1 but not 2: $name ";
+                }
+            }
+            if (exists $fail{views}{notexist}{2}) {
+                for my $name (@{$fail{views}{notexist}{2}}) {
+                    $db->{perf} .= " View in 2 but not 1: $name ";
+                }
+            }
+        }
+        if (exists $fail{views}{diffowners}) {
+            for my $item (@{$fail{views}{diffowners}}) {
+                my ($name,$owner1,$owner2) = @$item;
+                $db->{perf} .= qq{ View "$name" owned by "$owner1" on 1, but by "$owner2" on 2. };
+            }
+        }
+        if (exists $fail{views}{diffacls}) {
+            for my $item (@{$fail{views}{diffacls}}) {
+                my ($name,$acl1,$acl2) = @$item;
+                $db->{perf} .= qq{ View "$name" has $acl1 perms on 1, but $acl2 perms on 2. };
+            }
+        }
+        if (exists $fail{views}{diffdef}) {
+            for my $item (@{$fail{views}{diffdef}}) {
+                $db->{perf} .= qq{ View "$item" is different on 1 and 2. };
+            }
+        }
+    }
+
+    ## Trigger differences
+    if (exists $fail{triggers}) {
+        if (exists $fail{triggers}{notexist}) {
+            if (exists $fail{triggers}{notexist}{1}) {
+                for my $row (@{$fail{triggers}{notexist}{1}}) {
+                    my ($name,$tabname) = @$row;
+                    $db->{perf} .= " Trigger in 1 but not 2: $name (on $tabname) ";
+                }
+            }
+            if (exists $fail{triggers}{notexist}{2}) {
+                for my $row (@{$fail{triggers}{notexist}{2}}) {
+                    my ($name,$tabname) = @$row;
+                    $db->{perf} .= " Trigger in 2 but not 1: $name (on $tabname) ";
+                }
+            }
+        }
+        if (exists $fail{triggers}{difffunc}) {
+            for my $item (@{$fail{triggers}{diffowners}}) {
+                my ($name,$func1,$func2) = @$item;
+                $db->{perf} .= qq{ Trigger "$name" calls function "$func1" on 1, but function "$func2" on 2. };
+            }
+        }
+    }
+
+    ## Column differences
+    if (exists $fail{columns}) {
+        if (exists $fail{columns}{notexist}) {
+            if (exists $fail{columns}{notexist}{1}) {
+                for my $row (@{$fail{columns}{notexist}{1}}) {
+                    my ($tname,$cname) = @$row;
+                    $db->{perf} .= qq{ Table "$tname" on 1 has column "$cname", but 2 does not. };
+                }
+            }
+            if (exists $fail{columns}{notexist}{2}) {
+                for my $row (@{$fail{columns}{notexist}{2}}) {
+                    my ($tname,$cname) = @$row;
+                    $db->{perf} .= qq{ Table "$tname" on 2 has column "$cname", but 1 does not. };
+                }
+            }
+        }
+        if (exists $fail{columns}{diff}) {
+            for my $tname (sort keys %{$fail{columns}{diff}}) {
+                for my $cname (sort keys %{$fail{columns}{diff}{$tname}}) {
+                    for my $var (sort keys %{$fail{columns}{diff}{$tname}{$cname}}) {
+                        my ($v1,$v2) = @{$fail{columns}{diff}{$tname}{$cname}{$var}};
+                        $db->{perf} .= qq{ Column "$cname" of "$tname": $var is $v1 on 1, but $v2 on 2. };
+                    }
+                }
+            }
+        }
+    }
+
+    ## Constraint differences - table level
+    ## Don't report things twice
+    my %doublec;
+    if (exists $fail{constraints}) {
+        if (exists $fail{constraints}{notexist}) {
+            if (exists $fail{constraints}{notexist}{1}) {
+                for my $row (@{$fail{constraints}{notexist}{1}}) {
+                    my ($cname,$tname) = @$row;
+                    $db->{perf} .= qq{ Table "$tname" on 1 has constraint "$cname", but 2 does not. };
+                    $doublec{$cname}++;
+                }
+            }
+            if (exists $fail{constraints}{notexist}{2}) {
+                for my $row (@{$fail{constraints}{notexist}{2}}) {
+                    my ($cname,$tname) = @$row;
+                    $db->{perf} .= qq{ Table "$tname" on 2 has constraint "$cname", but 1 does not. };
+                    $doublec{$cname}++;
+                }
+            }
+        }
+        if (exists $fail{constraints}{tablediff}) {
+            for my $row (@{$fail{constraints}{tablediff}}) {
+                my ($cname,$t1,$t2) = @$row;
+                $db->{perf} .= qq{ Constraint "$cname" is applied to "$t1" on 1, but to "$t2" on 2. };
+                $doublec{$cname}++;
+            }
+        }
+    }
+
+    ## Constraint differences - column level
+    if (exists $fail{colconstraints}) {
+        if (exists $fail{colconstraints}{notexist}) {
+            if (exists $fail{colconstraints}{notexist}{1}) {
+                for my $row (@{$fail{colconstraints}{notexist}{1}}) {
+                    my ($name,$tname,$cname) = @$row;
+                    if (! exists $doublec{$name}) {
+                        $db->{perf} .= qq{ Table "$tname" on 1 has constraint "$name" on column "$cname", but 2 does not. };
+                    }
+                    else {
+                        $failcount--;
+                    }
+                }
+            }
+            if (exists $fail{colconstraints}{notexist}{2}) {
+                for my $row (@{$fail{colconstraints}{notexist}{2}}) {
+                    my ($name,$tname,$cname) = @$row;
+                    if (! exists $doublec{$name}) {
+                        $db->{perf} .= qq{ Table "$tname" on 2 has constraint "$name" on column "$cname", but 1 does not. };
+                    }
+                    else {
+                        $failcount--;
+                    }
+                }
+            }
+        }
+        if (exists $fail{colconstraints}{tablediff}) {
+            for my $row (@{$fail{colconstraints}{tablediff}}) {
+                my ($name,$t1,$t2) = @$row;
+                if (! exists $doublec{$name}) {
+                    $db->{perf} .= qq{ Constraint "$name" is applied to "$t1" on 1, but to "$t2" on 2. };
+                }
+                else {
+                    $failcount--;
+                }
+            }
+        }
+        if (exists $fail{colconstraints}{columndiff}) {
+            for my $row (@{$fail{colconstraints}{columndiff}}) {
+                my ($name,$t1,$c1,$t2,$c2) = @$row;
+                if (! exists $doublec{$name}) {
+                    $db->{perf} .= qq{ Constraint "$name" on 1 is applied to $t1.$c1, but to $t2.$c2 on 2. };
+                }
+                else {
+                    $failcount--;
+                }
+            }
+        }
+        if (exists $fail{colconstraints}{defdiff}) {
+            for my $row (@{$fail{colconstraints}{defdiff}}) {
+                my ($name,$t1,$c1,$d1,$t2,$c2,$d2) = @$row;
+                if (! exists $doublec{$name}) {
+                    $db->{perf} .= qq{ Constraint "$name" on 1 differs from 2 ("$d1" vs. "$d2") };
+                }
+                else {
+                    $failcount--;
+                }
+            }
+        }
+    }
+
+    ## Function differences
+    if (exists $fail{functions}) {
+        if (exists $fail{functions}{notexist}) {
+            if (exists $fail{functions}{notexist}{1}) {
+                for my $name (@{$fail{functions}{notexist}{1}}) {
+                    $db->{perf} .= " Function on 1 but not 2: $name ";
+                }
+            }
+            if (exists $fail{functions}{notexist}{2}) {
+                for my $name (@{$fail{functions}{notexist}{2}}) {
+                    $db->{perf} .= " Function on 2 but not 1: $name ";
+                }
+            }
+        }
+        if (exists $fail{functions}{diffbody}) {
+            for my $name (sort @{$fail{functions}{diffbody}}) {
+                $db->{perf} .= " Function body different on 1 than 2: $name ";
+            }
+        }
+        if (exists $fail{functions}{diffstrict}) {
+            for my $name (sort @{$fail{functions}{diffbody}}) {
+                $db->{perf} .= " Function strictness different on 1 than 2: $name ";
+            }
+        }
+        if (exists $fail{functions}{diffretset}) {
+            for my $name (sort @{$fail{functions}{diffretset}}) {
+                $db->{perf} .= " Function return-set different on 1 than 2: $name ";
+            }
+        }
+        if (exists $fail{functions}{diffvol}) {
+            for my $name (sort @{$fail{functions}{diffvol}}) {
+                $db->{perf} .= " Function volatilitiy different on 1 than 2: $name ";
+            }
+        }
+    }
+
+    ## Language differences
+    if (exists $fail{language}) {
+        if (exists $fail{language}{notexist}) {
+            if (exists $fail{language}{notexist}{1}) {
+                for my $name (@{$fail{language}{notexist}{1}}) {
+                    $db->{perf} .= " Language on 1 but not 2: $name ";
+                }
+            }
+            if (exists $fail{language}{notexist}{2}) {
+                for my $name (@{$fail{language}{notexist}{2}}) {
+                    $db->{perf} .= " Language on 2 but not 1: $name ";
+                }
+            }
+        }
+    }
+
+
+    add_critical msg('same-failed', $failcount);
+
+    return;
 
 } ## end of check_same_schema
 
 
 sub check_sequence {
 
-       ## Checks how many values are left in sequences
-       ## Supports: Nagios, MRTG
-       ## Warning and critical are percentages
-       ## Can exclude and include sequences
+    ## Checks how many values are left in sequences
+    ## Supports: Nagios, MRTG
+    ## Warning and critical are percentages
+    ## Can exclude and include sequences
 
-       my ($warning, $critical) = validate_range
-               ({
-                 type              => 'percent',
-                 default_warning   => '85%',
-                 default_critical  => '95%',
-                 forcemrtg         => 1,
-       });
+    my ($warning, $critical) = validate_range
+        ({
+          type              => 'percent',
+          default_warning   => '85%',
+          default_critical  => '95%',
+          forcemrtg         => 1,
+    });
 
-       (my $w = $warning) =~ s/\D//;
-       (my $c = $critical) =~ s/\D//;
+    (my $w = $warning) =~ s/\D//;
+    (my $c = $critical) =~ s/\D//;
 
-       ## Gather up all sequence names
-       my $SQL = q{
+    ## Gather up all sequence names
+    my $SQL = q{
 SELECT DISTINCT ON (nspname, seqname) nspname, seqname,
   quote_ident(nspname) || '.' || quote_ident(seqname) AS safename, typname
   -- sequences by column dependency
@@ -6306,25 +6306,25 @@ FROM (
 ORDER BY nspname, seqname, typname
 };
 
-       my $info = run_command($SQL, {regex => qr{\w}, emptyok => 1} );
-
-       my $MAXINT2 = 32767;
-       my $MAXINT4 = 2147483647;
-       my $MAXINT8 = 9223372036854775807;
-
-       my $limit = 0;
-
-       for $db (@{$info->{db}}) {
-               my (@crit,@warn,@ok);
-               my $maxp = 0;
-               my %seqinfo;
-               my %seqperf;
-               my $multidb = @{$info->{db}} > 1 ? "$db->{dbname}." : '';
-               for my $r (@{$db->{slurp}}) {
-                       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{
+    my $info = run_command($SQL, {regex => qr{\w}, emptyok => 1} );
+
+    my $MAXINT2 = 32767;
+    my $MAXINT4 = 2147483647;
+    my $MAXINT8 = 9223372036854775807;
+
+    my $limit = 0;
+
+    for $db (@{$info->{db}}) {
+        my (@crit,@warn,@ok);
+        my $maxp = 0;
+        my %seqinfo;
+        my %seqperf;
+        my $multidb = @{$info->{db}} > 1 ? "$db->{dbname}." : '';
+        for my $r (@{$db->{slurp}}) {
+            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,
   CASE WHEN slots < used THEN 0 ELSE slots - used END AS numleft
 FROM (
@@ -6334,153 +6334,153 @@ FROM (
 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 / };
-                       if (! defined $last) {
-                               ndie msg('seq-die', $seqname);
-                       }
-                       my $msg = msg('seq-msg', $seqname, $percent, $left);
-                       $seqperf{$percent}{$seqname} = [$left, " $multidb$seqname=$percent|$slots|$used|$left"];
-                       if ($percent >= $maxp) {
-                               $maxp = $percent;
-                               if (! exists $opt{perflimit} or $limit++ < $opt{perflimit}) {
-                                       push @{$seqinfo{$percent}} => $MRTG ? [$seqname,$percent,$slots,$used,$left] : $msg;
-                               }
-                       }
-                       next if $MRTG;
-
-                       if (length $critical and $percent >= $c) {
-                               push @crit => $msg;
-                       }
-                       elsif (length $warning and $percent >= $w) {
-                               push @warn => $msg;
-                       }
-               }
-               if ($MRTG) {
-                       my $msg = join ' | ' => map { $_->[0] } @{$seqinfo{$maxp}};
-                       do_mrtg({one => $maxp, msg => $msg});
-               }
-               $limit = 0;
-               PERF: for my $val (sort { $b <=> $a } keys %seqperf) {
-                       for my $seq (sort { $seqperf{$val}{$a}->[0] <=> $seqperf{$val}{$b}->[0] or $a cmp $b } keys %{$seqperf{$val}}) {
-                               last PERF if exists $opt{perflimit} and $limit++ >= $opt{perflimit};
-                               $db->{perf} .= $seqperf{$val}{$seq}->[1];
-                       }
-               }
-
-               if (@crit) {
-                       add_critical join ' ' => @crit;
-               }
-               elsif (@warn) {
-                       add_warning join ' ' => @warn;
-               }
-               else {
-                       if (keys %seqinfo) {
-                               add_ok join ' ' => @{$seqinfo{$maxp}};
-                       }
-                       else {
-                               add_ok msg('seq-none');
-                       }
-               }
-       }
-
-       return;
+            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 / };
+            if (! defined $last) {
+                ndie msg('seq-die', $seqname);
+            }
+            my $msg = msg('seq-msg', $seqname, $percent, $left);
+            $seqperf{$percent}{$seqname} = [$left, " $multidb$seqname=$percent|$slots|$used|$left"];
+            if ($percent >= $maxp) {
+                $maxp = $percent;
+                if (! exists $opt{perflimit} or $limit++ < $opt{perflimit}) {
+                    push @{$seqinfo{$percent}} => $MRTG ? [$seqname,$percent,$slots,$used,$left] : $msg;
+                }
+            }
+            next if $MRTG;
+
+            if (length $critical and $percent >= $c) {
+                push @crit => $msg;
+            }
+            elsif (length $warning and $percent >= $w) {
+                push @warn => $msg;
+            }
+        }
+        if ($MRTG) {
+            my $msg = join ' | ' => map { $_->[0] } @{$seqinfo{$maxp}};
+            do_mrtg({one => $maxp, msg => $msg});
+        }
+        $limit = 0;
+        PERF: for my $val (sort { $b <=> $a } keys %seqperf) {
+            for my $seq (sort { $seqperf{$val}{$a}->[0] <=> $seqperf{$val}{$b}->[0] or $a cmp $b } keys %{$seqperf{$val}}) {
+                last PERF if exists $opt{perflimit} and $limit++ >= $opt{perflimit};
+                $db->{perf} .= $seqperf{$val}{$seq}->[1];
+            }
+        }
+
+        if (@crit) {
+            add_critical join ' ' => @crit;
+        }
+        elsif (@warn) {
+            add_warning join ' ' => @warn;
+        }
+        else {
+            if (keys %seqinfo) {
+                add_ok join ' ' => @{$seqinfo{$maxp}};
+            }
+            else {
+                add_ok msg('seq-none');
+            }
+        }
+    }
+
+    return;
 
 } ## end of check_sequence
 
 
 sub check_settings_checksum {
 
-       ## Verify the checksum of all settings
-       ## Supports: Nagios, MRTG
-       ## Not that this will vary from user to user due to ALTER USER
-       ## and because superusers see additional settings
-       ## One of warning or critical must be given (but not both)
-       ## It should run one time to find out the expected checksum
-       ## You can use --critical="0" to find out the checksum
-       ## You can include or exclude settings as well
-       ## Example:
-       ##  check_postgres_settings_checksum --critical="4e7ba68eb88915d3d1a36b2009da4acd"
-
-       my ($warning, $critical) = validate_range({type => 'checksum', onlyone => 1});
-
-       eval {
-               require Digest::MD5;
-       };
-       if ($@) {
-               ndie msg('checksum-nomd');
-       }
-
-       $SQL = 'SELECT name, setting FROM pg_settings ORDER BY name';
-       my $info = run_command($SQL, { regex => qr[client_encoding] });
-
-       for $db (@{$info->{db}}) {
-
-               my $newstring = '';
-               for my $r (@{$db->{slurp}}) {
-                       next SLURP if skip_item($r->{name});
-                       $newstring .= "$r->{name} $r->{setting}\n";
-               }
-               if (! length $newstring) {
-                       add_unknown msg('no-match-set');
-               }
-
-               my $checksum = Digest::MD5::md5_hex($newstring);
-
-               my $msg = msg('checksum-msg', $checksum);
-               if ($MRTG) {
-                       $opt{mrtg} or ndie msg('checksum-nomrtg');
-                       do_mrtg({one => $opt{mrtg} eq $checksum ? 1 : 0, msg => $checksum});
-               }
-               if ($critical and $critical ne $checksum) {
-                       add_critical $msg;
-               }
-               elsif ($warning and $warning ne $checksum) {
-                       add_warning $msg;
-               }
-               elsif (!$critical and !$warning) {
-                       add_unknown $msg;
-               }
-               else {
-                       add_ok $msg;
-               }
-       }
-
-       return;
+    ## Verify the checksum of all settings
+    ## Supports: Nagios, MRTG
+    ## Not that this will vary from user to user due to ALTER USER
+    ## and because superusers see additional settings
+    ## One of warning or critical must be given (but not both)
+    ## It should run one time to find out the expected checksum
+    ## You can use --critical="0" to find out the checksum
+    ## You can include or exclude settings as well
+    ## Example:
+    ##  check_postgres_settings_checksum --critical="4e7ba68eb88915d3d1a36b2009da4acd"
+
+    my ($warning, $critical) = validate_range({type => 'checksum', onlyone => 1});
+
+    eval {
+        require Digest::MD5;
+    };
+    if ($@) {
+        ndie msg('checksum-nomd');
+    }
+
+    $SQL = 'SELECT name, setting FROM pg_settings ORDER BY name';
+    my $info = run_command($SQL, { regex => qr[client_encoding] });
+
+    for $db (@{$info->{db}}) {
+
+        my $newstring = '';
+        for my $r (@{$db->{slurp}}) {
+            next SLURP if skip_item($r->{name});
+            $newstring .= "$r->{name} $r->{setting}\n";
+        }
+        if (! length $newstring) {
+            add_unknown msg('no-match-set');
+        }
+
+        my $checksum = Digest::MD5::md5_hex($newstring);
+
+        my $msg = msg('checksum-msg', $checksum);
+        if ($MRTG) {
+            $opt{mrtg} or ndie msg('checksum-nomrtg');
+            do_mrtg({one => $opt{mrtg} eq $checksum ? 1 : 0, msg => $checksum});
+        }
+        if ($critical and $critical ne $checksum) {
+            add_critical $msg;
+        }
+        elsif ($warning and $warning ne $checksum) {
+            add_warning $msg;
+        }
+        elsif (!$critical and !$warning) {
+            add_unknown $msg;
+        }
+        else {
+            add_ok $msg;
+        }
+    }
+
+    return;
 
 } ## end of check_settings_checksum
 
 
 sub check_slony_status {
 
-       ## Checks the sl_status table
-       ## Returns unknown if sl_status is not found
-       ## Returns critical is status is not "good"
-       ## Otherwise, returns based on time-based warning and critical options
-       ## Supports: Nagios, MRTG
-
-       my ($warning, $critical) = validate_range
-               ({
-                 type              => 'time',
-                 default_warning   => '60',
-                 default_critical  => '300',
-               });
-
-       my $schema = $opt{schema} || '';
-
-       if (!$schema) {
-               $SQL = q{SELECT quote_ident(nspname) AS nspname FROM pg_namespace WHERE oid = }.
-                          q{(SELECT relnamespace FROM pg_class WHERE relkind = 'v' AND relname = 'sl_status' LIMIT 1)};
-               my $res = run_command($SQL);
-               if (! defined $res->{db}[0]{slurp}[0]{nspname}) {
-                       add_unknown msg('slony-noschema');
-                       return;
-               }
-               $schema = $res->{db}[0]{slurp}[0]{nspname};
-       }
-
-       my $SQL =
+    ## Checks the sl_status table
+    ## Returns unknown if sl_status is not found
+    ## Returns critical is status is not "good"
+    ## Otherwise, returns based on time-based warning and critical options
+    ## Supports: Nagios, MRTG
+
+    my ($warning, $critical) = validate_range
+        ({
+          type              => 'time',
+          default_warning   => '60',
+          default_critical  => '300',
+        });
+
+    my $schema = $opt{schema} || '';
+
+    if (!$schema) {
+        $SQL = q{SELECT quote_ident(nspname) AS nspname FROM pg_namespace WHERE oid = }.
+               q{(SELECT relnamespace FROM pg_class WHERE relkind = 'v' AND relname = 'sl_status' LIMIT 1)};
+        my $res = run_command($SQL);
+        if (! defined $res->{db}[0]{slurp}[0]{nspname}) {
+            add_unknown msg('slony-noschema');
+            return;
+        }
+        $schema = $res->{db}[0]{slurp}[0]{nspname};
+    }
+
+    my $SQL =
 qq{SELECT
  ROUND(EXTRACT(epoch FROM st_lag_time)) AS lagtime,
  st_origin,
@@ -6492,177 +6492,177 @@ FROM $schema.sl_status
 JOIN $schema.sl_node n1 ON (n1.no_id=st_origin)
 JOIN $schema.sl_node n2 ON (n2.no_id=st_received)};
 
-       my $info = run_command($SQL);
-       $db = $info->{db}[0];
-       if (! defined $db->{slurp}[0]{lagtime}) {
-               add_unknown msg('slony-nonumber');
-               return;
-       }
-       my $maxlagtime = 0;
-       my @perf;
-       for my $r (@{$db->{slurp}}) {
-               if (! defined $r->{lagtime}) {
-                       add_unknown msg('slony-noparse');
-               }
-               my ($lag,$from,$to,$dbname,$fromc,$toc) = @$r{qw/ lagtime st_origin st_received cd com1 com2/};
-               $maxlagtime = $lag if $lag > $maxlagtime;
-               push @perf => [
-                              $lag,
-                              $from,
-                              qq{'$dbname Node $from($fromc) -> Node $to($toc)'=$lag;$warning;$critical},
-                              ];
-       }
-       $db->{perf} = join "\n" => map { $_->[2] } sort { $b->[0]<=>$a->[0] or $a->[1]<=>$b->[1] } @perf;
-       if ($MRTG) {
-               do_mrtg({one => $maxlagtime});
-               return;
-       }
-       my $msg = msg('slony-lagtime', $maxlagtime);
-       $msg .= sprintf ' (%s)', pretty_time($maxlagtime, $maxlagtime > 500 ? 'S' : '');
-       if (length $critical and $maxlagtime >= $critical) {
-               add_critical $msg;
-       }
-       elsif (length $warning and $maxlagtime >= $warning) {
-               add_warning $msg;
-       }
-       else {
-               add_ok $msg;
-       }
-
-       return;
+    my $info = run_command($SQL);
+    $db = $info->{db}[0];
+    if (! defined $db->{slurp}[0]{lagtime}) {
+        add_unknown msg('slony-nonumber');
+        return;
+    }
+    my $maxlagtime = 0;
+    my @perf;
+    for my $r (@{$db->{slurp}}) {
+        if (! defined $r->{lagtime}) {
+            add_unknown msg('slony-noparse');
+        }
+        my ($lag,$from,$to,$dbname,$fromc,$toc) = @$r{qw/ lagtime st_origin st_received cd com1 com2/};
+        $maxlagtime = $lag if $lag > $maxlagtime;
+        push @perf => [
+                   $lag,
+                   $from,
+                   qq{'$dbname Node $from($fromc) -> Node $to($toc)'=$lag;$warning;$critical},
+                   ];
+    }
+    $db->{perf} = join "\n" => map { $_->[2] } sort { $b->[0]<=>$a->[0] or $a->[1]<=>$b->[1] } @perf;
+    if ($MRTG) {
+        do_mrtg({one => $maxlagtime});
+        return;
+    }
+    my $msg = msg('slony-lagtime', $maxlagtime);
+    $msg .= sprintf ' (%s)', pretty_time($maxlagtime, $maxlagtime > 500 ? 'S' : '');
+    if (length $critical and $maxlagtime >= $critical) {
+        add_critical $msg;
+    }
+    elsif (length $warning and $maxlagtime >= $warning) {
+        add_warning $msg;
+    }
+    else {
+        add_ok $msg;
+    }
+
+    return;
 
 } ## end of check_slony_status
 
 sub check_timesync {
 
-       ## Compare local time to the database time
-       ## Supports: Nagios, MRTG
-       ## Warning and critical are given in number of seconds difference
-
-       my ($warning,$critical) = validate_range
-               ({
-                 type             => 'seconds',
-                 default_warning  => 2,
-                 default_critical => 5,
-                 });
-
-       $SQL = q{SELECT round(extract(epoch FROM now())) AS epok, TO_CHAR(now(),'YYYY-MM-DD HH24:MI:SS') AS pretti};
-       my $info = run_command($SQL);
-       my $localepoch = time;
-       my @l = localtime;
-
-       for $db (@{$info->{db}}) {
-               my ($pgepoch,$pgpretty) = @{$db->{slurp}->[0]}{qw/ epok pretti /};
-
-               my $diff = abs($pgepoch - $localepoch);
-               if ($MRTG) {
-                       $stats{$db->{dbname}} = $diff;
-                       next;
-               }
-               $db->{perf} = msg('timesync-diff', $diff);
-               my $localpretty = sprintf '%d-%02d-%02d %02d:%02d:%02d', $l[5]+1900, $l[4]+1, $l[3],$l[2],$l[1],$l[0];
-               my $msg = msg('timesync-msg', $diff, $pgpretty, $localpretty);
-
-               if (length $critical and $diff >= $critical) {
-                       add_critical $msg;
-               }
-               elsif (length $warning and $diff >= $warning) {
-                       add_warning $msg;
-               }
-               else {
-                       add_ok $msg;
-               }
-       }
-       return;
+    ## Compare local time to the database time
+    ## Supports: Nagios, MRTG
+    ## Warning and critical are given in number of seconds difference
+
+    my ($warning,$critical) = validate_range
+        ({
+          type             => 'seconds',
+          default_warning  => 2,
+          default_critical => 5,
+          });
+
+    $SQL = q{SELECT round(extract(epoch FROM now())) AS epok, TO_CHAR(now(),'YYYY-MM-DD HH24:MI:SS') AS pretti};
+    my $info = run_command($SQL);
+    my $localepoch = time;
+    my @l = localtime;
+
+    for $db (@{$info->{db}}) {
+        my ($pgepoch,$pgpretty) = @{$db->{slurp}->[0]}{qw/ epok pretti /};
+
+        my $diff = abs($pgepoch - $localepoch);
+        if ($MRTG) {
+            $stats{$db->{dbname}} = $diff;
+            next;
+        }
+        $db->{perf} = msg('timesync-diff', $diff);
+        my $localpretty = sprintf '%d-%02d-%02d %02d:%02d:%02d', $l[5]+1900, $l[4]+1, $l[3],$l[2],$l[1],$l[0];
+        my $msg = msg('timesync-msg', $diff, $pgpretty, $localpretty);
+
+        if (length $critical and $diff >= $critical) {
+            add_critical $msg;
+        }
+        elsif (length $warning and $diff >= $warning) {
+            add_warning $msg;
+        }
+        else {
+            add_ok $msg;
+        }
+    }
+    return;
 
 } ## end of check_timesync
 
 
 sub check_txn_idle {
 
-       ## Check the length of "idle in transaction" connections
-       ## Supports: Nagios, MRTG
-       ## It makes no sense to run this more than once on the same cluster
-       ## Warning and critical are time limits - defaults to seconds
-       ## Valid units: s[econd], m[inute], h[our], d[ay]
-       ## All above may be written as plural as well (e.g. "2 hours")
-       ## Can also ignore databases with exclude and limit with include
-       ## Limit to a specific user with the includeuser option
-       ## Exclude users with the excludeuser option
-
-       my ($warning, $critical) = validate_range
-               ({
-               type => 'time',
-               });
-
-
-       $SQL = q{SELECT datname, max(COALESCE(ROUND(EXTRACT(epoch FROM now()-query_start)),0)) AS maxx }.
-               qq{FROM pg_stat_activity WHERE current_query = '<IDLE> in transaction'$USERWHERECLAUSE GROUP BY 1};
-
-       my $info = run_command($SQL, { emptyok => 1 } );
-
-       my $found = 0;
-       for $db (@{$info->{db}}) {
-               my $max = -1;
-               for my $r (@{$db->{slurp}}) {
-                       $found++;
-                       my ($dbname,$current) = ($r->{datname}, int $r->{maxx});
-                       next if skip_item($dbname);
-                       $max = $current if $current > $max;
-               }
-               if ($MRTG) {
-                       $stats{$db->{dbname}} = $max < 0 ? 0 : $max;
-                       next;
-               }
-               $db->{perf} .= msg('maxtime', $max);
-               if ($max < 0) {
-                       add_unknown msg('txnidle-none');
-                       next;
-               }
-
-               my $msg = msg('txnidle-msg', $max);
-               if (length $critical and $max >= $critical) {
-                       add_critical $msg;
-               }
-               elsif (length $warning and $max >= $warning) {
-                       add_warning $msg;
-               }
-               else {
-                       add_ok $msg;
-               }
-       }
-
-       ## If no results, let's be paranoid and check their settings
-       if (!$found) {
-               if ($USERWHERECLAUSE) {
-                       add_ok msg('no-match-user');
-               }
-               verify_version();
-       }
-
-       return;
+    ## Check the length of "idle in transaction" connections
+    ## Supports: Nagios, MRTG
+    ## It makes no sense to run this more than once on the same cluster
+    ## Warning and critical are time limits - defaults to seconds
+    ## Valid units: s[econd], m[inute], h[our], d[ay]
+    ## All above may be written as plural as well (e.g. "2 hours")
+    ## Can also ignore databases with exclude and limit with include
+    ## Limit to a specific user with the includeuser option
+    ## Exclude users with the excludeuser option
+
+    my ($warning, $critical) = validate_range
+        ({
+        type => 'time',
+        });
+
+
+    $SQL = q{SELECT datname, max(COALESCE(ROUND(EXTRACT(epoch FROM now()-query_start)),0)) AS maxx }.
+        qq{FROM pg_stat_activity WHERE current_query = '<IDLE> in transaction'$USERWHERECLAUSE GROUP BY 1};
+
+    my $info = run_command($SQL, { emptyok => 1 } );
+
+    my $found = 0;
+    for $db (@{$info->{db}}) {
+        my $max = -1;
+        for my $r (@{$db->{slurp}}) {
+            $found++;
+            my ($dbname,$current) = ($r->{datname}, int $r->{maxx});
+            next if skip_item($dbname);
+            $max = $current if $current > $max;
+        }
+        if ($MRTG) {
+            $stats{$db->{dbname}} = $max < 0 ? 0 : $max;
+            next;
+        }
+        $db->{perf} .= msg('maxtime', $max);
+        if ($max < 0) {
+            add_unknown msg('txnidle-none');
+            next;
+        }
+
+        my $msg = msg('txnidle-msg', $max);
+        if (length $critical and $max >= $critical) {
+            add_critical $msg;
+        }
+        elsif (length $warning and $max >= $warning) {
+            add_warning $msg;
+        }
+        else {
+            add_ok $msg;
+        }
+    }
+
+    ## If no results, let's be paranoid and check their settings
+    if (!$found) {
+        if ($USERWHERECLAUSE) {
+            add_ok msg('no-match-user');
+        }
+        verify_version();
+    }
+
+    return;
 
 } ## end of check_txn_idle
 
 
 sub check_txn_time {
 
-       ## Check the length of running transactions
-       ## Supports: Nagios, MRTG
-       ## It makes no sense to run this more than once on the same cluster
-       ## Warning and critical are time limits - defaults to seconds
-       ## Valid units: s[econd], m[inute], h[our], d[ay]
-       ## All above may be written as plural as well (e.g. "2 hours")
-       ## Can also ignore databases with exclude and limit with include
-       ## Limit to a specific user with the includeuser option
-       ## Exclude users with the excludeuser option
-
-       my ($warning, $critical) = validate_range
-               ({
-               type => 'time',
-               });
-
-       $SQL = qq{
+    ## Check the length of running transactions
+    ## Supports: Nagios, MRTG
+    ## It makes no sense to run this more than once on the same cluster
+    ## Warning and critical are time limits - defaults to seconds
+    ## Valid units: s[econd], m[inute], h[our], d[ay]
+    ## All above may be written as plural as well (e.g. "2 hours")
+    ## Can also ignore databases with exclude and limit with include
+    ## Limit to a specific user with the includeuser option
+    ## Exclude users with the excludeuser option
+
+    my ($warning, $critical) = validate_range
+        ({
+        type => 'time',
+        });
+
+    $SQL = qq{
 SELECT
  client_addr,
  client_port,
@@ -6674,250 +6674,250 @@ FROM pg_stat_activity
 WHERE xact_start IS NOT NULL $USERWHERECLAUSE
 };
 
-       my $info = run_command($SQL, { regex => qr{\d+ \|\s+\s+}, emptyok => 1 } );
-
-       $db = $info->{db}[0];
-       my $slurp = $db->{slurp};
-
-       if (! exists $db->{ok}) {
-               ndie msg('txntime-fail');
-       }
-
-       if ($slurp !~ /\w/ and $USERWHERECLAUSE) {
-               $stats{$db->{dbname}} = 0;
-               add_ok msg('no-match-user');
-               return;
-       }
-
-       ## Default values for information gathered
-       my ($client_addr, $client_port, $procpid, $username, $maxtime, $maxdb) = ('0.0.0.0', 0, '?', 0, 0, '?');
-
-       ## Read in and parse the psql output
-       for my $r (@{$db->{slurp}}) {
-               my ($add,$port,$pid,$time,$dbname,$user) = @$r{qw/ client_addr client_port procpid username maxtime maxdb /};
-               next if skip_item($dbname);
-
-               if ($time >= $maxtime) {
-                       $maxtime     = $time;
-                       $maxdb       = $dbname;
-                       $client_addr = $add;
-                       $client_port = $port;
-                       $procpid     = $pid;
-                       $username    = $user;
-               }
-       }
-
-       ## Use of skip_item means we may have no matches
-       if ($maxdb eq '?') {
-               if ($USERWHERECLAUSE) { ## needed?
-                       add_unknown msg('tttt-nomatch');
-               }
-               else {
-                       add_ok msg('txntime-none');
-               }
-               return;
-       }
-
-       ## Details on who the offender was
-       my $whodunit = sprintf q{%s:%s %s:%s%s%s %s:%s},
-               msg('database'),
-               $maxdb,
-               msg('PID'),
-               $procpid,
-               $client_port < 1 ? '' : (sprintf ' %s:%s', msg('port'), $client_port),
-               $client_addr eq '' ? '' : (sprintf ' %s:%s', msg('address'), $client_addr),
-               msg('username'),
-               $username;
-
-       $MRTG and do_mrtg({one => $maxtime, msg => $whodunit});
-
-       $db->{perf} .= sprintf q{'%s'=%s;%s;%s},
-               $whodunit,
-               $maxtime,
-               $warning,
-               $critical;
-
-       my $msg = sprintf '%s (%s)', msg('qtime-msg', $maxtime), $whodunit;
-
-       if (length $critical and $maxtime >= $critical) {
-               add_critical $msg;
-       }
-       elsif (length $warning and $maxtime >= $warning) {
-               add_warning $msg;
-       }
-       else {
-               add_ok $msg;
-       }
-
-       return;
+    my $info = run_command($SQL, { regex => qr{\d+ \|\s+\s+}, emptyok => 1 } );
+
+    $db = $info->{db}[0];
+    my $slurp = $db->{slurp};
+
+    if (! exists $db->{ok}) {
+        ndie msg('txntime-fail');
+    }
+
+    if ($slurp !~ /\w/ and $USERWHERECLAUSE) {
+        $stats{$db->{dbname}} = 0;
+        add_ok msg('no-match-user');
+        return;
+    }
+
+    ## Default values for information gathered
+    my ($client_addr, $client_port, $procpid, $username, $maxtime, $maxdb) = ('0.0.0.0', 0, '?', 0, 0, '?');
+
+    ## Read in and parse the psql output
+    for my $r (@{$db->{slurp}}) {
+        my ($add,$port,$pid,$time,$dbname,$user) = @$r{qw/ client_addr client_port procpid username maxtime maxdb /};
+        next if skip_item($dbname);
+
+        if ($time >= $maxtime) {
+            $maxtime     = $time;
+            $maxdb       = $dbname;
+            $client_addr = $add;
+            $client_port = $port;
+            $procpid     = $pid;
+            $username    = $user;
+        }
+    }
+
+    ## Use of skip_item means we may have no matches
+    if ($maxdb eq '?') {
+        if ($USERWHERECLAUSE) { ## needed?
+            add_unknown msg('tttt-nomatch');
+        }
+        else {
+            add_ok msg('txntime-none');
+        }
+        return;
+    }
+
+    ## Details on who the offender was
+    my $whodunit = sprintf q{%s:%s %s:%s%s%s %s:%s},
+        msg('database'),
+        $maxdb,
+        msg('PID'),
+        $procpid,
+        $client_port < 1 ? '' : (sprintf ' %s:%s', msg('port'), $client_port),
+        $client_addr eq '' ? '' : (sprintf ' %s:%s', msg('address'), $client_addr),
+        msg('username'),
+        $username;
+
+    $MRTG and do_mrtg({one => $maxtime, msg => $whodunit});
+
+    $db->{perf} .= sprintf q{'%s'=%s;%s;%s},
+        $whodunit,
+        $maxtime,
+        $warning,
+        $critical;
+
+    my $msg = sprintf '%s (%s)', msg('qtime-msg', $maxtime), $whodunit;
+
+    if (length $critical and $maxtime >= $critical) {
+        add_critical $msg;
+    }
+    elsif (length $warning and $maxtime >= $warning) {
+        add_warning $msg;
+    }
+    else {
+        add_ok $msg;
+    }
+
+    return;
 
 } ## end of check_txn_time
 
 
 sub check_txn_wraparound {
 
-       ## Check how close to transaction wraparound we are on all databases
-       ## Supports: Nagios, MRTG
-       ## Warning and critical are the number of transactions performed
-       ## Thus, anything *over* that number will trip the alert
-       ## See: http://www.postgresql.org/docs/current/static/routine-vacuuming.html#VACUUM-FOR-WRAPAROUND
-       ## It makes no sense to run this more than once on the same cluster
-
-       my ($warning, $critical) = validate_range
-               ({
-                 type             => 'positive integer',
-                 default_warning  => 1_300_000_000,
-                 default_critical => 1_400_000_000,
-                 });
-
-       if ($warning and $warning >= 2_000_000_000) {
-               ndie msg('txnwrap-wbig');
-       }
-       if ($critical and $critical >= 2_000_000_000) {
-               ndie msg('txnwrap-cbig');
-       }
-
-       $SQL = q{SELECT datname, age(datfrozenxid) AS age FROM pg_database WHERE datallowconn ORDER BY 1, 2};
-       my $info = run_command($SQL, { regex => qr[\w+\s+\|\s+\d+] } );
-
-       my ($mrtgmax,$mrtgmsg) = (0,'?');
-       for $db (@{$info->{db}}) {
-               my ($max,$msg) = (0,'?');
-               for my $r (@{$db->{slurp}}) {
-                       my ($dbname,$dbtxns) = ($r->{datname},$r->{age});
-                       $db->{perf} .= " '$dbname'=$dbtxns;";
-                       $db->{perf} .= $warning if length $warning;
-                       $db->{perf} .= ';';
-                       $db->{perf} .= $critical if length $critical;
-                       $db->{perf} .= ';0;2000000000';
-                       next SLURP if skip_item($dbname);
-                       if ($dbtxns > $max) {
-                               $max = $dbtxns;
-                               $msg = qq{$dbname: $dbtxns};
-                               if ($dbtxns > $mrtgmax) {
-                                       $mrtgmax = $dbtxns;
-                                       $mrtgmsg = "DB: $dbname";
-                               }
-                       }
-               }
-               if (length $critical and $max >= $critical) {
-                       add_critical $msg;
-               }
-               elsif (length $warning and $max >= $warning) {
-                       add_warning $msg;
-               }
-               else {
-                       add_ok $msg;
-               }
-       }
-       $MRTG and do_mrtg({one => $mrtgmax, msg => $mrtgmsg});
-
-       return;
+    ## Check how close to transaction wraparound we are on all databases
+    ## Supports: Nagios, MRTG
+    ## Warning and critical are the number of transactions performed
+    ## Thus, anything *over* that number will trip the alert
+    ## See: http://www.postgresql.org/docs/current/static/routine-vacuuming.html#VACUUM-FOR-WRAPAROUND
+    ## It makes no sense to run this more than once on the same cluster
+
+    my ($warning, $critical) = validate_range
+        ({
+          type             => 'positive integer',
+          default_warning  => 1_300_000_000,
+          default_critical => 1_400_000_000,
+          });
+
+    if ($warning and $warning >= 2_000_000_000) {
+        ndie msg('txnwrap-wbig');
+    }
+    if ($critical and $critical >= 2_000_000_000) {
+        ndie msg('txnwrap-cbig');
+    }
+
+    $SQL = q{SELECT datname, age(datfrozenxid) AS age FROM pg_database WHERE datallowconn ORDER BY 1, 2};
+    my $info = run_command($SQL, { regex => qr[\w+\s+\|\s+\d+] } );
+
+    my ($mrtgmax,$mrtgmsg) = (0,'?');
+    for $db (@{$info->{db}}) {
+        my ($max,$msg) = (0,'?');
+        for my $r (@{$db->{slurp}}) {
+            my ($dbname,$dbtxns) = ($r->{datname},$r->{age});
+            $db->{perf} .= " '$dbname'=$dbtxns;";
+            $db->{perf} .= $warning if length $warning;
+            $db->{perf} .= ';';
+            $db->{perf} .= $critical if length $critical;
+            $db->{perf} .= ';0;2000000000';
+            next SLURP if skip_item($dbname);
+            if ($dbtxns > $max) {
+                $max = $dbtxns;
+                $msg = qq{$dbname: $dbtxns};
+                if ($dbtxns > $mrtgmax) {
+                    $mrtgmax = $dbtxns;
+                    $mrtgmsg = "DB: $dbname";
+                }
+            }
+        }
+        if (length $critical and $max >= $critical) {
+            add_critical $msg;
+        }
+        elsif (length $warning and $max >= $warning) {
+            add_warning $msg;
+        }
+        else {
+            add_ok $msg;
+        }
+    }
+    $MRTG and do_mrtg({one => $mrtgmax, msg => $mrtgmsg});
+
+    return;
 
 } ## end of check_txn_wraparound
 
 
 sub check_version {
 
-       ## Compare version with what we think it should be
-       ## Supports: Nagios, MRTG
-       ## Warning and critical are the major and minor (e.g. 8.3)
-       ## or the major, minor, and revision (e.g. 8.2.4 or even 8.3beta4)
-
-       if ($MRTG) {
-               if (!exists $opt{mrtg} or $opt{mrtg} !~ /^\d+\.\d+/) {
-                       ndie msg('version-badmrtg');
-               }
-               if ($opt{mrtg} =~ /^\d+\.\d+$/) {
-                       $opt{critical} = $opt{mrtg};
-               }
-               else {
-                       $opt{warning} = $opt{mrtg};
-               }
-       }
-
-       my ($warning, $critical) = validate_range({type => 'version', forcemrtg => 1});
-
-       my ($warnfull, $critfull) = (($warning =~ /^\d+\.\d+$/ ? 0 : 1),($critical =~ /^\d+\.\d+$/ ? 0 : 1));
-
-       my $info = run_command('SELECT version() AS version');
-
-       for $db (@{$info->{db}}) {
-               my $row = $db->{slurp}[0];
-               if ($row->{version} !~ /PostgreSQL ((\d+\.\d+)(\w+|\.\d+))/o) {
-                       add_unknown msg('invalid-query', $row->{version});
-                       next;
-               }
-               my ($full,$version,$revision) = ($1,$2,$3||'?');
-               $revision =~ s/^\.//;
-
-               my $ok = 1;
-
-               if (length $critical) {
-                       if (($critfull and $critical ne $full)
-                               or (!$critfull and $critical ne $version)) {
-                               $MRTG and do_mrtg({one => 0, msg => $full});
-                               add_critical msg('version-fail', $full, $critical);
-                               $ok = 0;
-                       }
-               }
-               elsif (length $warning) {
-                       if (($warnfull and $warning ne $full)
-                               or (!$warnfull and $warning ne $version)) {
-                               $MRTG and do_mrtg({one => 0, msg => $full});
-                               add_warning msg('version-fail', $full, $warning);
-                               $ok = 0;
-                       }
-               }
-               if ($ok) {
-                       $MRTG and do_mrtg({one => 1, msg => $full});
-                       add_ok msg('version-ok', $full);
-               }
-       }
-
-       return;
+    ## Compare version with what we think it should be
+    ## Supports: Nagios, MRTG
+    ## Warning and critical are the major and minor (e.g. 8.3)
+    ## or the major, minor, and revision (e.g. 8.2.4 or even 8.3beta4)
+
+    if ($MRTG) {
+        if (!exists $opt{mrtg} or $opt{mrtg} !~ /^\d+\.\d+/) {
+            ndie msg('version-badmrtg');
+        }
+        if ($opt{mrtg} =~ /^\d+\.\d+$/) {
+            $opt{critical} = $opt{mrtg};
+        }
+        else {
+            $opt{warning} = $opt{mrtg};
+        }
+    }
+
+    my ($warning, $critical) = validate_range({type => 'version', forcemrtg => 1});
+
+    my ($warnfull, $critfull) = (($warning =~ /^\d+\.\d+$/ ? 0 : 1),($critical =~ /^\d+\.\d+$/ ? 0 : 1));
+
+    my $info = run_command('SELECT version() AS version');
+
+    for $db (@{$info->{db}}) {
+        my $row = $db->{slurp}[0];
+        if ($row->{version} !~ /PostgreSQL ((\d+\.\d+)(\w+|\.\d+))/o) {
+            add_unknown msg('invalid-query', $row->{version});
+            next;
+        }
+        my ($full,$version,$revision) = ($1,$2,$3||'?');
+        $revision =~ s/^\.//;
+
+        my $ok = 1;
+
+        if (length $critical) {
+            if (($critfull and $critical ne $full)
+                or (!$critfull and $critical ne $version)) {
+                $MRTG and do_mrtg({one => 0, msg => $full});
+                add_critical msg('version-fail', $full, $critical);
+                $ok = 0;
+            }
+        }
+        elsif (length $warning) {
+            if (($warnfull and $warning ne $full)
+                or (!$warnfull and $warning ne $version)) {
+                $MRTG and do_mrtg({one => 0, msg => $full});
+                add_warning msg('version-fail', $full, $warning);
+                $ok = 0;
+            }
+        }
+        if ($ok) {
+            $MRTG and do_mrtg({one => 1, msg => $full});
+            add_ok msg('version-ok', $full);
+        }
+    }
+
+    return;
 
 } ## end of check_version
 
 
 sub check_wal_files {
 
-       ## Check on the number of WAL files in use
-       ## Supports: Nagios, MRTG
-       ## Must run as a superuser
-       ## Critical and warning are the number of files
-       ## Example: --critical=40
-
-       my ($warning, $critical) = validate_range({type => 'integer', leastone => 1});
-
-       ## Figure out where the pg_xlog directory is
-       $SQL = q{SELECT count(*) AS count FROM pg_ls_dir('pg_xlog') WHERE pg_ls_dir ~ E'^[0-9A-F]{24}$'}; ## no critic (RequireInterpolationOfMetachars)
-
-       my $info = run_command($SQL, {regex => qr[\d] });
-
-       my $found = 0;
-       for $db (@{$info->{db}}) {
-               my $r = $db->{slurp}[0];
-               my $numfiles = $r->{count};
-               if ($MRTG) {
-                       $stats{$db->{dbname}} = $numfiles;
-                       $statsmsg{$db->{dbname}} = '';
-                       next;
-               }
-               my $msg = qq{$numfiles};
-               $db->{perf} .= " '$db->{host}'=$numfiles;$warning;$critical";
-               if (length $critical and $numfiles > $critical) {
-                       add_critical $msg;
-               }
-               elsif (length $warning and $numfiles > $warning) {
-                       add_warning $msg;
-               }
-               else {
-                       add_ok $msg;
-               }
-       }
-
-       return;
+    ## Check on the number of WAL files in use
+    ## Supports: Nagios, MRTG
+    ## Must run as a superuser
+    ## Critical and warning are the number of files
+    ## Example: --critical=40
+
+    my ($warning, $critical) = validate_range({type => 'integer', leastone => 1});
+
+    ## Figure out where the pg_xlog directory is
+    $SQL = q{SELECT count(*) AS count FROM pg_ls_dir('pg_xlog') WHERE pg_ls_dir ~ E'^[0-9A-F]{24}$'}; ## no critic (RequireInterpolationOfMetachars)
+
+    my $info = run_command($SQL, {regex => qr[\d] });
+
+    my $found = 0;
+    for $db (@{$info->{db}}) {
+        my $r = $db->{slurp}[0];
+        my $numfiles = $r->{count};
+        if ($MRTG) {
+            $stats{$db->{dbname}} = $numfiles;
+            $statsmsg{$db->{dbname}} = '';
+            next;
+        }
+        my $msg = qq{$numfiles};
+        $db->{perf} .= " '$db->{host}'=$numfiles;$warning;$critical";
+        if (length $critical and $numfiles > $critical) {
+            add_critical $msg;
+        }
+        elsif (length $warning and $numfiles > $warning) {
+            add_warning $msg;
+        }
+        else {
+            add_ok $msg;
+        }
+    }
+
+    return;
 
 } ## end of check_wal_files