PGObject-Util-DBAdmin-1.6.1/0000755000175000017500000000000014141757620014000 5ustar erikerikPGObject-Util-DBAdmin-1.6.1/t/0000755000175000017500000000000014141757620014243 5ustar erikerikPGObject-Util-DBAdmin-1.6.1/t/perlcriticrc0000644000175000017500000000515614123341763016657 0ustar erikerik# Run just the policies listed in this configuration only = 1 # Fail if listed policy modules are not available profile-strictness = fatal verbose =%s %p %f %l\n [RegularExpressions::ProhibitCaptureWithoutTest] [ErrorHandling::RequireCarping] # Policies taken from main ledgersmb project [BuiltinFunctions::ProhibitBooleanGrep] [BuiltinFunctions::ProhibitStringySplit] [BuiltinFunctions::ProhibitUniversalCan] [BuiltinFunctions::ProhibitUniversalIsa] [ClassHierarchies::ProhibitExplicitISA] [CodeLayout::ProhibitHardTabs] allow_leading_tabs = 0 [CodeLayout::ProhibitTrailingWhitespace] [ControlStructures::ProhibitMutatingListFunctions] [ControlStructures::ProhibitUnreachableCode] [InputOutput::ProhibitBarewordFileHandles] [InputOutput::ProhibitInteractiveTest] [InputOutput::ProhibitOneArgSelect] [InputOutput::ProhibitTwoArgOpen] [InputOutput::RequireCheckedClose] [InputOutput::RequireCheckedOpen] [InputOutput::RequireCheckedSyscalls] [InputOutput::RequireEncodingWithUTF8Layer] [Miscellanea::ProhibitFormats] [Modules::ProhibitAutomaticExportation] [Modules::ProhibitConditionalUseStatements] [Modules::ProhibitEvilModules] [Modules::ProhibitExcessMainComplexity] [Modules::ProhibitMultiplePackages] [Modules::RequireBarewordIncludes] [Modules::RequireEndWithOne] [Modules::RequireExplicitInclusion] [Modules::RequireExplicitPackage] [Modules::RequireFilenameMatchesPackage] [Modules::RequireNoMatchVarsWithUseEnglish] [Objects::ProhibitIndirectSyntax] [Subroutines::ProhibitExplicitReturnUndef] [Subroutines::ProhibitReturnSort] [Subroutines::ProhibitSubroutinePrototypes] [Subroutines::ProtectPrivateSubs] [Subroutines::RequireFinalReturn] [TestingAndDebugging::ProhibitNoStrict] [TestingAndDebugging::ProhibitNoWarnings] [TestingAndDebugging::ProhibitProlongedStrictureOverride] [TestingAndDebugging::RequireTestLabels] [TestingAndDebugging::RequireUseStrict] [TestingAndDebugging::RequireUseWarnings] [ValuesAndExpressions::ProhibitCommaSeparatedStatements] [ValuesAndExpressions::ProhibitInterpolationOfLiterals] [ValuesAndExpressions::ProhibitMagicNumbers] allowed_values = -1 0 1 2 100 [ValuesAndExpressions::ProhibitMismatchedOperators] [ValuesAndExpressions::ProhibitMixedBooleanOperators] [Variables::ProhibitPerl4PackageNames] [Variables::ProhibitUnusedVariables] [Variables::ProtectPrivateVars] [Variables::RequireInitializationForLocalVars] [Variables::RequireLexicalLoopIterators] [Variables::RequireLocalizedPunctuationVars] # Not applied # # Because we use octal values to refer to file permissions # Wrapping each of these in an oct(..) as Perl::Critic suggests # harms readability. # [ValuesAndExpressions::ProhibitLeadingZeros] PGObject-Util-DBAdmin-1.6.1/t/data/0000755000175000017500000000000014141757620015154 5ustar erikerikPGObject-Util-DBAdmin-1.6.1/t/data/an_existing_file0000644000175000017500000000000014123341763020371 0ustar erikerikPGObject-Util-DBAdmin-1.6.1/t/data/backup.sqlc0000644000175000017500000000377114123341763017312 0ustar erikerikPGDMP ! rtest_db9.3.59.3.5 # 00ENCODINGENCODINGSET client_encoding = 'UTF8'; false$ 00 STDSTRINGS STDSTRINGS(SET standard_conforming_strings = 'on'; false% 1262280335test_dbDATABASEyCREATE DATABASE test_db WITH TEMPLATE = template0 ENCODING = 'UTF8' LC_COLLATE = 'en_US.UTF-8' LC_CTYPE = 'en_US.UTF-8'; DROP DATABASE test_db; chrisfalse26152200publicSCHEMACREATE SCHEMA public; DROP SCHEMA public; postgresfalse& 00 SCHEMA publicCOMMENT6COMMENT ON SCHEMA public IS 'standard public schema'; postgresfalse6' 00publicACL¢REVOKE ALL ON SCHEMA public FROM PUBLIC; REVOKE ALL ON SCHEMA public FROM postgres; GRANT ALL ON SCHEMA public TO postgres; GRANT ALL ON SCHEMA public TO PUBLIC; postgresfalse6«307912669plpgsql EXTENSION?CREATE EXTENSION IF NOT EXISTS plpgsql WITH SCHEMA pg_catalog; DROP EXTENSION plpgsql; false( 00EXTENSION plpgsqlCOMMENT@COMMENT ON EXTENSION plpgsql IS 'PL/pgSQL procedural language'; false171ª1259280336 test_dataTABLE*CREATE TABLE test_data ( test text ); DROP TABLE public.test_data; publicchrisfalse6 0280336 test_data TABLE DATA"COPY test_data (test) FROM stdin; publicchrisfalse170Ú xœ3äŠÑãââZäPGObject-Util-DBAdmin-1.6.1/t/data/bad.sql0000644000175000017500000000004014123341763016412 0ustar erikerikCREATE TABLE foo (bar, text, ); PGObject-Util-DBAdmin-1.6.1/t/data/schema.sql0000644000175000017500000000011714123341763017131 0ustar erikerikCREATE TABLE test_data ( test text ); INSERT INTO test_data (test) values (1); PGObject-Util-DBAdmin-1.6.1/t/00.2-load.t0000644000175000017500000000040714123341763015722 0ustar erikerik#!perl -T use 5.006; use strict; use warnings FATAL => 'all'; use Test::More; plan tests => 1; BEGIN { use_ok( 'PGObject::Util::DBAdmin' ) || print "Bail out!\n"; } diag( "Testing PGObject::Util::DBAdmin $PGObject::Util::DBAdmin::VERSION, Perl $], $^X" ); PGObject-Util-DBAdmin-1.6.1/t/00.1-critic.t0000644000175000017500000000143514123341763016261 0ustar erikerikuse strict; use warnings; use Test::More; # plan automatically generated below use File::Find; use Perl::Critic; use Perl::Critic::Violation; my @on_disk; sub test_files { my ($critic, $files) = @_; Perl::Critic::Violation::set_format( 'S%s %p %f: %l\n'); for my $file (@$files) { my @findings = $critic->critique($file); ok(scalar(@findings) == 0, "Critique for $file"); for my $finding (@findings) { diag ("$finding"); } } return; } sub collect { return if $File::Find::name !~ m/\.(pm|pl|t)$/; my $module = $File::Find::name; push @on_disk, $module } find(\&collect, 'lib/'); plan tests => scalar(@on_disk); test_files( Perl::Critic->new( -profile => 't/perlcriticrc', ), \@on_disk ); PGObject-Util-DBAdmin-1.6.1/t/manifest.t0000644000175000017500000000050714123341763016235 0ustar erikerik#!perl -T use 5.006; use strict; use warnings FATAL => 'all'; use Test::More; unless ( $ENV{RELEASE_TESTING} ) { plan( skip_all => "Author tests not required for installation" ); } my $min_tcm = 0.9; eval "use Test::CheckManifest $min_tcm"; plan skip_all => "Test::CheckManifest $min_tcm required" if $@; ok_manifest(); PGObject-Util-DBAdmin-1.6.1/t/pod.t0000644000175000017500000000040114123341763015202 0ustar erikerik#!perl -T use 5.006; use strict; use warnings FATAL => 'all'; use Test::More; # Ensure a recent version of Test::Pod my $min_tp = 1.22; eval "use Test::Pod $min_tp"; plan skip_all => "Test::Pod $min_tp required for testing POD" if $@; all_pod_files_ok(); PGObject-Util-DBAdmin-1.6.1/t/01.1-dbtests.t0000644000175000017500000001071014123341763016451 0ustar erikerikuse warnings; use strict; use Test::More; use Test::Exception; use PGObject::Util::DBAdmin; use File::Temp; plan skip_all => 'DB_TESTING not set' unless $ENV{DB_TESTING}; plan tests => 75; # Constructor my $dbh; my $db; ok($db = PGObject::Util::DBAdmin->new( username => 'postgres', password => $ENV{PGPASSWORD}, dbname => 'pgobject_test_db', host => $ENV{PGHOST} // 'localhost', port => $ENV{PGPORT} // '5432' ), 'Created db admin object'); # Drop db if exists eval { $db->drop }; # List dbs my @dblist; ok(@dblist = $db->list_dbs, 'Got a db list'); ok (!grep {$_ eq 'pgobject_test_db'} @dblist, 'DB list does not contain pgobject_test_db'); # Create db $db->create; ok($db->server_version, 'Got a server version'); ok (grep {$_ eq 'pgobject_test_db'} $db->list_dbs, 'DB list does contain pgobject_test_db after create call'); # load with schema - valid sql my $stdout_log = File::Temp->new->filename; my $stderr_log = File::Temp->new->filename; ok($db->run_file( file => 't/data/schema.sql', stdout_log => $stdout_log, errlog => $stderr_log, ), 'Loaded schema'); ok(-f $stdout_log, 'run_file stdout_log file written'); ok(-f $stderr_log, 'run_file errlog file written'); cmp_ok(-s $stdout_log, '>', 0, 'run_file stdout_log file has size > 0 for valid sql'); cmp_ok(-s $stderr_log, '==', 0, 'run_file errlog file has size == 0 for valid sql'); ok(defined $db->stdout, 'after run_file stdout property is defined'); cmp_ok(length $db->stdout, '>', 0, 'after run_file, stdout property has length > 0'); ok(defined $db->stderr, 'after run_file stderr property is defined'); cmp_ok(length $db->stderr, '==', 0, 'after run_file, stderr property has length == 0 for valid sql'); unlink $stdout_log; unlink $stderr_log; ok ($dbh = $db->connect, 'Got dbi handle'); my ($foo) = @{ $dbh->selectall_arrayref('select count(*) from test_data') }; is ($foo->[0], 1, 'Correct count of data') ; $dbh->disconnect; # backup/drop/create/restore, formats undef, p, and c foreach my $format ((undef, 'p', 'c')) { my $display_format = $format || 'undef'; # Test backing up to specified file my $output_file = File::Temp->new->filename; my $backup; ok($backup = $db->backup( format => $format, file => $output_file, ), "Made backup to specified file, format $display_format"); ok($backup =~ m|^$output_file$|, 'backup respects file parameter'); ok(-f $backup, "backup format $display_format output file exists"); cmp_ok(-s $backup, '>', 0, "backup format $display_format output file has size > 0"); unlink $backup; # Test backing up to auto-generated temp file ok($backup = $db->backup( format => $format, tempdir => 't/var/', ), "Made backup, format $display_format"); ok($backup =~ m|^t/var/|, 'backup respects tempdir parameter'); ok(-f $backup, "backup format $display_format output file exists"); cmp_ok(-s $backup, '>', 0, "backup format $display_format output file has size > 0"); ok($db->drop, "dropped db, format $display_format"); ok (!(grep{$_ eq 'pgobject_test_db'} @dblist), 'DB list does not contain pgobject_test_db'); dies_ok { $db->restore( format => $format, file => 't/data/does-not-exist', ) } "die when restore file does not exist, format $display_format"; ok($db->create, "created db, format $display_format"); ok($dbh = $db->connect, "Got dbi handle, format $display_format"); ok($db->restore( format => $format, file => $backup, ), "Restored backup, format $display_format"); ok(defined $db->stderr, 'stderr captured during restore'); ok(defined $db->stdout, 'stdout captured during restore'); ok(($foo) = $dbh->selectall_arrayref('select count(*) from test_data'), "Got results from test data count, format $display_format"); is($foo->[0]->[0], 1, "correct data count, format $display_format"); $dbh->disconnect; unlink $backup; } # Test backing up to compressed auto-generated temp file my $backup; my $fh; ok($backup = $db->backup( tempdir => 't/var/', compress => 9, ), "Made backup, compressed"); ok(-f $backup, "backup, compressed output file exists"); cmp_ok(-s $backup, '>', 0, "backup, compressed output file has size > 0"); ok(open ($fh, '<', $backup), "backup, compressed output file opened successfully"); like(<$fh>, qr/^\x1F\x8B/, 'backup, compressed output file is gzip format'); unlink $backup; PGObject-Util-DBAdmin-1.6.1/t/pod-coverage.t0000644000175000017500000000111314123341763016774 0ustar erikerik#!perl -T use 5.006; use strict; use warnings FATAL => 'all'; use Test::More; # Ensure a recent version of Test::Pod::Coverage my $min_tpc = 1.08; eval "use Test::Pod::Coverage $min_tpc"; plan skip_all => "Test::Pod::Coverage $min_tpc required for testing POD coverage" if $@; # Test::Pod::Coverage doesn't require a minimum Pod::Coverage version, # but older versions don't recognize some common documentation styles my $min_pc = 0.18; eval "use Pod::Coverage $min_pc"; plan skip_all => "Pod::Coverage $min_pc required for testing POD coverage" if $@; all_pod_coverage_ok(); PGObject-Util-DBAdmin-1.6.1/t/01.3-verify-helpers.t0000644000175000017500000000207414123341763017753 0ustar erikerikuse warnings; use strict; use Test::More; use PGObject::Util::DBAdmin; if (not $ENV{AUTHOR_TESTING}) { plan skip_all => 'Test only applicable when AUTHOR_TESTING'; } else { plan tests => 3; } is_deeply( PGObject::Util::DBAdmin->verify_helpers, { map { $_ => 1 } keys %PGObject::Util::DBAdmin::helper_paths }, 'Without arguments, test all helpers'); is_deeply( PGObject::Util::DBAdmin->verify_helpers( operations => [ keys %PGObject::Util::DBAdmin::helpers ] ), { map { $_ => 1 } keys %PGObject::Util::DBAdmin::helper_paths }, 'With the "operations" argument, test the associated helpers'); is_deeply( PGObject::Util::DBAdmin->verify_helpers( helpers => [ keys %PGObject::Util::DBAdmin::helper_paths ] ), { map { $_ => 1 } keys %PGObject::Util::DBAdmin::helper_paths }, 'With the "helpers" argument, test the associated helpers'); PGObject-Util-DBAdmin-1.6.1/t/boilerplate.t0000644000175000017500000000241314123341763016727 0ustar erikerik#!perl -T use 5.006; use strict; use warnings FATAL => 'all'; use Test::More; plan tests => 3; sub not_in_file_ok { my ($filename, %regex) = @_; open( my $fh, '<', $filename ) or die "couldn't open $filename for reading: $!"; my %violated; while (my $line = <$fh>) { while (my ($desc, $regex) = each %regex) { if ($line =~ $regex) { push @{$violated{$desc}||=[]}, $.; } } } if (%violated) { fail("$filename contains boilerplate text"); diag "$_ appears on lines @{$violated{$_}}" for keys %violated; } else { pass("$filename contains no boilerplate text"); } } sub module_boilerplate_ok { my ($module) = @_; not_in_file_ok($module => 'the great new $MODULENAME' => qr/ - The great new /, 'boilerplate description' => qr/Quick summary of what the module/, 'stub function definition' => qr/function[12]/, ); } not_in_file_ok(README => "The README is used..." => qr/The README is used/, "'version information here'" => qr/to provide version information/, ); not_in_file_ok(Changes => "placeholder date/time" => qr(Date/time) ); module_boilerplate_ok('lib/PGObject/Util/DBAdmin.pm'); PGObject-Util-DBAdmin-1.6.1/t/02-dbexceptions.t0000644000175000017500000000634314123341763017341 0ustar erikerikuse warnings; use strict; use Test::More; use File::Temp; use PGObject::Util::DBAdmin; use Test::Exception; plan skip_all => 'DB_TESTING not set' unless $ENV{DB_TESTING}; plan tests => 24; my $db = PGObject::Util::DBAdmin->new( username => 'postgres' , host => 'localhost' , port => '5432' , dbname => 'pgobject_test_db', ); eval { $db->drop }; lives_ok { $db->create } 'Create db, none exists'; dies_ok { $db->create } 'create db, already exists'; dies_ok { $db->run_file(file => 't/data/does_not_exist.sql') } 'bad file input for run_file'; # try to load with invalid sql my $stdout_log = File::Temp->new->filename; my $stderr_log = File::Temp->new->filename; dies_ok{ $db->run_file( file => 't/data/bad.sql', stdout_log => $stdout_log, errlog => $stderr_log, ) } 'run_file dies with bad sql'; ok(-f $stdout_log, 'run_file stdout_log file written'); ok(-f $stderr_log, 'run_file errlog file written'); ok(defined $db->stdout, 'after run_file stdout property is defined'); ok(defined $db->stderr, 'after run_file stderr property is defined'); cmp_ok(-s $stdout_log, '==', 0, 'run_file stdout_log file has size == 0 for invalid sql'); cmp_ok(-s $stderr_log, '>', 0, 'run_file errlog file has size > 0 for invalid sql'); cmp_ok(length $db->stdout, '==', 0, 'after run_file, stdout property has length == 0 for invalid sql'); cmp_ok(length $db->stderr, '>', 0, 'after run_file, stderr property has length > 0 for invalid sql'); unlink $stdout_log; unlink $stderr_log; # Test that restore fails with bad input # Note cannot use format=undef of format='c' as these options # actually call run_file underneath dies_ok{ $db->restore( file => 't/data/bad.sql', format => 't', ) } 'restore dies with bad input'; lives_ok { $db->drop } 'drop db first time, successful'; dies_ok { $db->drop } 'dropdb second time, dies'; my $backup_file = File::Temp->new->filename; dies_ok { $db->backup(format => 'c', file => $backup_file) } 'cannot back up non-existent db'; ok(! -e $backup_file, 'output file deleted after backup error'); # Test what happens if specified backup file is unwriteable my $temp = File::Temp->new; $backup_file = $temp->filename; chmod 0400, $backup_file; dies_ok { $db->backup(format => 'c', file => $backup_file) } 'backup dies if output file is not writeable'; chmod 0600, $backup_file; unlink $backup_file; dies_ok { $db->restore(format => 'c', file => 't/data/backup.sqlc') } 'cannot restore to non-existent db'; $db = PGObject::Util::DBAdmin->new( username => 'invalid', host => 'localhost', port => '5432', dbname => 'pgobject_test_db', ); $backup_file = File::Temp->new->filename; dies_ok { $db->backup_globals(file => $backup_file) } 'backup_globals dies with bad username'; ok(! -e $backup_file, 'output file deleted after backup_globals error'); dies_ok { $db->backup(format => 'c', file => $backup_file) } 'backup dies with bad username'; ok(! -e $backup_file, 'output file deleted after backup error'); $db = PGObject::Util::DBAdmin->new( username => 'postgres' , host => 'localhost' , port => '2' , dbname => 'pgobject_test_db', ); dies_ok { $db->connect } 'Could not connect'; PGObject-Util-DBAdmin-1.6.1/t/01.2-backup_globals.t0000644000175000017500000000644314123341763017762 0ustar erikerikuse warnings; use strict; use Test::More; use Test::Exception; use PGObject::Util::DBAdmin; use File::Temp; plan skip_all => 'DB_TESTING not set' unless $ENV{DB_TESTING}; plan tests => 21; # Constructor my $dbh; my $db; my $temp; my $backup_file; ok($db = PGObject::Util::DBAdmin->new( username => 'postgres', password => undef, dbname => 'pgobject_test_db', host => 'localhost', port => '5432' ), 'Created db admin object'); # Drop db if exists eval { $db->drop }; # Test backup_globals to auto-generated temp file ok($backup_file = $db->backup_globals( tempdir => 't/var/', ), 'backup_globals outputs to auto-generated file'); ok(-f $backup_file, 'backup_globals output to auto-generated file exists'); ok($backup_file =~ m|^t/var/|, 'backup_globals output to auto-generated file respects tempdir parameter'); cmp_ok(-s $backup_file, '>', 0, 'backup_globals output to auto-generated file has size > 0'); is((stat($backup_file))[2] & 07777, 0600, 'backup_globals output to auto-generated file has permissions 0600'); unlink $backup_file; # Test backup_globals to not-existing specified file $temp = File::Temp->new->filename; ok(!-f $temp, 'backup_globals non-existent specified file does not exist'); ok($backup_file = $db->backup_globals( file => $temp, ), 'backup_globals outputs to non-existent specified file'); ok(-f $backup_file, 'backup_globals output to non-existent specified file exists'); ok($temp =~ m/^$backup_file$/, 'backup_globals output to non-existent specified file respects file parameter'); cmp_ok(-s $backup_file, '>', 0, 'backup_globals output to non-existent specified file has size > 0'); is((stat($backup_file))[2] & 07777, 0600, 'backup_globals output to non-existent specified file has permissions 0600'); unlink $backup_file; # Test backup_globals to overwrite existing specified file with 'wrong' permssions # Makes sure that file is written and permissions are unchanged $temp = File::Temp->new; chmod 0777, $temp->filename; # Give it wrong permissions is((stat($temp->filename))[2] & 07777, 0777, 'specified backup_globals output file created with permissions 0777'); ok($backup_file = $db->backup_globals( file => $temp->filename, ), 'backup_globals outputs to existing specified file with permissions 0777'); ok($temp->filename =~ m/^$backup_file$/, 'backup_globals output to existing specified file respects file parameter'); cmp_ok(-s $backup_file, '>', 0, 'backup_globals output to existing specified file with permissions 0777 has size > 0'); is((stat($backup_file))[2] & 07777, 0777, 'backup_globals output to existing specified file retains permissions 0777'); undef $temp; # Test backup_globals to overwrite existing specified file with 'right' permssions # Make sure file is written and 'correct' 0600 permissions are retained $temp = File::Temp->new; is((stat($temp->filename))[2] & 07777, 0600, 'specified backup_globals output file created with permissions 0600'); ok($backup_file = $db->backup_globals( file => $temp->filename, ), 'backup globals outut to existing specified file with permissions 0600'); cmp_ok(-s $backup_file, '>', 0, 'backup_globals to existing specified file with permissions 0600 has size > 0'); is((stat($backup_file))[2] & 07777, 0600, 'backup_globals output to existing specified file retains permissions 0600'); undef $temp; PGObject-Util-DBAdmin-1.6.1/t/03-file_errors.t0000644000175000017500000000301614123341763017160 0ustar erikerikuse warnings; use strict; use File::Temp; use Test::More; use PGObject::Util::DBAdmin; use Test::Exception; plan skip_all => 'DB_TESTING not set' unless $ENV{DB_TESTING}; plan tests => 8; my $output_file = File::Temp->new->filename; my $db = PGObject::Util::DBAdmin->new( username => 'postgres' , host => 'localhost' , port => '5432' , dbname => 'pgobject_test_db', ); dies_ok { $db->backup( tempdir => 'This_directory_does_not_exist' ) } 'backup db with non-existent tempdir'; dies_ok { $db->backup( format => 'THIS_IS_A_BAD_FORMAT', file => $output_file, ) } 'backup db with bad format'; dies_ok { $db->backup( file => 't/data/an_existing_file/cannot_write' ) } 'backup db cannot write to specified file'; dies_ok { $db->backup( tempdir => 't/data/an_existing_file' ) } 'backup db tempdir is an existing file'; dies_ok { $db->backup_globals( tempdir => 'This_directory_does_not_exist' ) } 'backup_globals with non-existent tempdir'; dies_ok { $db->backup_globals( file => 't/data/an_existing_file/cannot_write' ) } 'backup_globals cannot write to specified file'; dies_ok { $db->backup_globals( tempdir => 't/data/an_existing_file' ) } 'backup_globals tempdir is an existing file'; dies_ok { $db->restore( file => 't/data/an_existing_file', format => 'AN_INVALID_FORMAT', ) } 'restore method called with invalid format'; unlink $output_file; PGObject-Util-DBAdmin-1.6.1/lib/0000755000175000017500000000000014141757620014546 5ustar erikerikPGObject-Util-DBAdmin-1.6.1/lib/PGObject/0000755000175000017500000000000014141757620016203 5ustar erikerikPGObject-Util-DBAdmin-1.6.1/lib/PGObject/Util/0000755000175000017500000000000014141757620017120 5ustar erikerikPGObject-Util-DBAdmin-1.6.1/lib/PGObject/Util/DBAdmin.pm0000644000175000017500000006334014141757574020732 0ustar erikerikpackage PGObject::Util::DBAdmin; use 5.010; # Uses // defined-or operator use strict; use warnings FATAL => 'all'; use Capture::Tiny 'capture'; use Carp; use DBI; use File::Temp; use Log::Any; use Scope::Guard qw(guard); use Moo; use namespace::clean; =head1 NAME PGObject::Util::DBAdmin - PostgreSQL Database Management Facilities for PGObject =head1 VERSION version 1.6.1 =cut our $VERSION = '1.6.1'; =head1 SYNOPSIS This module provides an interface to the basic Postgres db manipulation utilities. my $db = PGObject::Util::DBAdmin->new( connect_data => { user => 'postgres', password => 'mypassword', host => 'localhost', port => '5432', dbname => 'mydb' } ); my @dbnames = $db->list_dbs(); # like psql -l $db->create(); # createdb $db->run_file(file => 'sql/initial_schema.sql'); # psql -f my $filename = $db->backup(format => 'c'); # pg_dump -Fc my $db2 = PGObject::Util::DBAdmin->new($db->export, (dbname => 'otherdb')); my $db3 = PGObject::Util::DBAdmin->new( connect_data => { service => 'zephyr', sslmode => 'require', sslkey => "$HOME/.postgresql/postgresql.key", sslcert => "$HOME/.postgresql/postgresql.crt", sslpassword => 'your-sslpassword', } ); =head1 PROPERTIES =head2 connect_data Contains a hash with connection parameters; see L for supported parameters. The usual parameters are: =over =item * user =item * password =item * dbname =item * host =item * port =back Please note that the key C is deprecated in favor of C and isn't supported. =cut # Not supported # PGSERVICEFILE: (because no connect string equiv) # PGREQUIRESSL: deprecated my %connkey_env = qw( host PGHOST hostaddr PGHOSTADDR dbname PGDATABASE user PGUSER password PGPASSWORD passfile PGPASSFILE channel_binding PGCHANNELBINDING service PGSERVICE options PGOPTIONS sslmode PGSSLMODE sslcompression PGSSLCOMPRESSION sslcert PGSSLCERT sslkey PGSSLKEY sslrootcert PGSSLROOTCERT sslcrl PGSSLCRL requirepeer PGREQUIREPEER ssl_min_protocol_version PGSSLMINPROTOCOLVERSION ssl_max_protocol_version PGSSLMAXPROTOCOLVERSION gssencmode PGGSSENCMODE krbsrvname PGKRBSRVNAME gsslib PGGSSLIB connect_timeout PGCONNECT_TIMEOUT client_encoding PGCLIENTENCODING target_session_attrs PGTARGETSESSIONATTRS ); my @connstr_keys = ((grep { not ($_ eq 'user' or $_ eq 'password') } keys %connkey_env), qw(application_name fallback_application_name keepalives keepalives_idle keepalives_interval keepalives_count tcp_user_timeout replication sslpassword), ); sub _connect_data_env { my ($connect_data) = @_; my @keys = grep { exists $connkey_env{$_} and defined $connect_data->{$_} } keys %$connect_data; return map { $connkey_env{$_} => $connect_data->{$_} } @keys; } sub _connect_data_str { my ($connect_data) = @_; my @keys = grep { defined $connect_data->{$_} } @connstr_keys; return join(';', map { my $val = $connect_data->{$_}; $val =~ s/\\/\\\\/g; $val =~ s/'/\\'/g; "$_='$val'"; } @keys ); } has connect_data => (is => 'ro'); =head2 username (deprecated) The username used to authenticate with the PostgreSQL server. =cut has username => (is => 'ro'); =head2 password (deprecated) The password used to authenticate with the PostgreSQL server. =cut has password => (is => 'ro'); =head2 host (deprecated) In PostgreSQL, this can refer to the hostname or the absolute path to the directory where the UNIX sockets are set up. =cut has host => (is => 'ro'); =head2 port (deprecated) Default '5432' =cut has port => (is => 'ro'); =head2 dbname (deprecated) The database name to create or connect to. =cut has dbname => (is => 'ro'); =head2 stderr When applicable, the stderr output captured from any external commands (for example createdb or pg_restore) run during the previous method call. See notes in L. =cut has stderr => (is => 'ro'); =head2 stdout When applicable, the stdout output captured from any external commands (for example createdb or pg_restore) run during the previous method call. See notes in L. =cut has stdout => (is => 'ro'); =head2 logger Provides a reference to the logger associated with the current instance. The logger uses C as its category, eliminating the need to create new loggers when deriving from this class. If you want to override the logger-instantiation behaviour, please implement the C<_build_logger> builder method in your derived class. =cut has logger => (is => 'ro', lazy => 1, builder => '_build_logger'); sub _build_logger { return Log::Any->get_logger(category => ref $_[0]); } our %helpers = ( create => [ qw/createdb/ ], run_file => [ qw/psql/ ], backup => [ qw/pg_dump/ ], backup_globals => [ qw/pg_dumpall/ ], restore => [ qw/pg_restore psql/ ], drop => [ qw/dropdb/ ], is_ready => [ qw/pg_isready/ ], ); =head1 GLOBAL VARIABLES =head2 %helper_paths This hash variable contains as its keys the names of the PostgreSQL helper executables C, C, C, etc. The values contain the paths at which the executables to be run are located. The default values are the names of the executables only, allowing them to be looked up in C<$PATH>. Modification of the values in this variable are the strict realm of I. Libraries using this library should defer potential required modifications to the applications based upon them. =cut our %helper_paths = ( psql => 'psql', dropdb => 'dropdb', createdb => 'createdb', pg_dump => 'pg_dump', pg_dumpall => 'pg_dumpall', pg_restore => 'pg_restore', pg_isready => 'pg_isready', ); sub _run_with_env { my %args = @_; my $env = $args{env}; local %ENV = ( # Note that we're intentionally *not* passing # PERL5LIB & PERL5OPT into the environment here! # doing so prevents the system settings to be used, which # we *do* want. If we don't, hopefully, that's coded into # the executables themselves. # Before using this whitelisting, coverage tests in LedgerSMB # would break on the bleeding through this caused. HOME => $ENV{HOME}, PATH => $ENV{PATH}, %{$env // {}}, ); return system @{$args{command}}; } sub _run_command { my ($self, %args) = @_; my $exit_code; my %env = ( # lowest priority: existing environment variables (map { $ENV{$_} ? ($_ => $ENV{$_}) : () } qw(PGUSER PGPASSWORD PGHOST PGPORT PGDATABASE PGSERVICE)), # overruled by middle priority: object connection parameters _connect_data_env($self->connect_data), # overruled by highest priority: specified environment ($args{env} ? %{$args{env}} : ()), ); $self->logger->debugf( sub { return 'Running with environment: ' . join(' ', map { qq|$_="$env{$_}"| } sort keys %env ); }); # Any files created should be accessible only by the current user my $original_umask = umask 0077; { my $guard = guard { umask $original_umask; }; ($self->{stdout}, $self->{stderr}, $exit_code) = capture { _run_with_env(%args, env => \%env); }; if(defined ($args{errlog} // $args{stdout_log})) { $self->_write_log_files(%args); } } if ($exit_code != 0) { for my $filename (@{$args{unlink}}) { unlink $filename or carp "error unlinking '$filename': $!"; } my $command = join( ' ', map { "'$_'" } @{$args{command}} ); my $err; if ($? == -1) { $err = "$!"; } elsif ($? & 127) { $err = sprintf('died with signal %d', ($? & 127)); } else { $err = sprintf('exited with code %d', ($? >> 8)); } croak "$args{error}; (command: $command): $err"; } return 1; } sub _generate_output_filename { my ($self, %args) = @_; # If caller has supplied a file path, use that # rather than generating our own temp file. defined $args{file} and return $args{file}; my %file_options = (UNLINK => 0); if(defined $args{tempdir}) { -d $args{tempdir} or croak "directory $args{tempdir} does not exist or is not a directory"; $file_options{DIR} = $args{tempdir}; } # File::Temp creates files with permissions 0600 my $fh = File::Temp->new(%file_options) or croak "could not create temp file: $@, $!"; return $fh->filename; } sub _write_log_files { my ($self, %args) = @_; defined $args{stdout_log} and $self->_append_to_file( $args{stdout_log}, $self->{stdout}, ); defined $args{errlog} and $self->_append_to_file( $args{errlog}, $self->{stderr}, ); return; } sub _append_to_file { my ($self, $filename, $data) = @_; open(my $fh, '>>', $filename) or croak "couldn't open file $filename for appending $!"; print $fh ($data // '') or croak "failed writing to file $!"; close $fh or croak "failed closing file $filename $!"; return; } =head1 SUBROUTINES/METHODS =head2 new Creates a new db admin object for manipulating databases. =head2 BUILDARGS Compensates for the legacy invocation with the C, C, C, C and C parameters. =head2 verify_helpers( [ helpers => [...]], [operations => [...]]) Verifies ability to execute (external) helper applications by method name (through the C argument) or by external helper name (through the C argument). Returns a hash ref with each key being the name of a helper application (see C below) with the values being a boolean indicating whether or not the helper can be successfully executed. Valid values in the array referenced by the C parameter are C, C, C, C, C and C; the methods this module implements with the help of external helper programs. (Other values may be passed, but unsupported values aren't included in the return value.) Valid values in the array referenced by the C parameter are the names of the PostgreSQL helper programs C, C, C, C, C and C. (Other values may be passed, but unsupported values will not be included in the return value.) When no arguments are passed, all helpers will be tested. Note: C is a class method, meaning it wants to be called as Cverify_helpers()>. =cut around 'BUILDARGS' => sub { my ($orig, $class, @args) = @_; ## 1.1.0 compatibility code (allow a reference to be passed in) my %args = (@args == 1 and ref $args[0]) ? (%{$args[0]}) : (@args); # deprecated field support code block if (exists $args{connect_data}) { # Work-around for 'export' creating the expectation that # parameters may be overridable; I've observed the pattern # ...->new($db->export, (dbname => 'newdb')) # which we "solve" by hacking the dbname arg into the connect_data # Don't overwrite connect_data, because it may be used elsewhere... $args{connect_data} = { %{$args{connect_data}}, dbname => ($args{dbname} // $args{connect_data}->{dbname}) }; # Now for legacy purposes hack the connection parameters into # connect_data $args{username} = $args{connect_data}->{user}; $args{$_} = $args{connect_data}->{$_} for (qw(password dbname host port)); } else { $args{connect_data} = {}; $args{connect_data}->{user} = $args{username}; $args{connect_data}->{password} = $args{password}; $args{connect_data}->{dbname} = $args{dbname}; $args{connect_data}->{host} = $args{host}; $args{connect_data}->{port} = $args{port}; } return $class->$orig(%args); }; sub _run_capturing_output { my @args = @_; my ($stdout, $stderr, $exitcode) = capture { _run_with_env(@args); }; return $exitcode; } sub verify_helpers { my ($class, %args) = @_; my @helpers = ( @{$args{helpers} // []}, map { @{$helpers{$_} // []} } @{$args{operations} // []} ); if (not @helpers) { @helpers = keys %helper_paths; } return { map { $_ => not _run_capturing_output(command => [ $helper_paths{$_} , '--help' ]) } @helpers }; } =head2 export Exports the database parameters as a list so it can be used to create another object. =cut sub export { my $self = shift; return ( connect_data => $self->connect_data ); } =head2 connect($options) Connects to the database using DBI and returns a database connection. Connection options may be specified in the $options hashref. =cut sub connect { my ($self, $options) = @_; my $connect = _connect_data_str($self->connect_data); my $dbh = DBI->connect( 'dbi:Pg:' . $connect, $self->connect_data->{user} // '', # suppress use of DBI_USER $self->connect_data->{password} // '',# suppress use of DBI_PASS $options ) or croak 'Could not connect to database: ' . $DBI::errstr; return $dbh; } =head2 server_version([$dbname]) Returns a version string (like 9.1.4) for PostgreSQL. Croaks on error. When a database name is specified, uses that database to connect to, using the credentials specified in the instance. If no database name is specified, 'template1' is used. =cut sub server_version { my $self = shift @_; my $dbname = (shift @_) || 'template1'; my $version = __PACKAGE__->new($self->export, (dbname => $dbname) )->connect->{pg_server_version}; my $retval = ''; while (1) { $retval = ($version % 100) . $retval; $version = int($version / 100); return $retval unless $version; $retval = ".$retval"; } } =head2 list_dbs([$dbname]) Returns a list of db names. When a database name is specified, uses that database to connect to, using the credentials specified in the instance. If no database name is specified, 'template1' is used. =cut sub list_dbs { my $self = shift; my $dbname = (shift @_) || 'template1'; return map { $_->[0] } @{ __PACKAGE__->new($self->export, (dbname => $dbname) )->connect->selectall_arrayref( 'SELECT datname from pg_database order by datname' ) }; } =head2 create Creates a new database. Croaks on error, returns true on success. Supported arguments: =over =item copy_of Creates the new database as a copy of the specified one (using it as a template). Optional parameter. Default is to create a database without a template. =back =cut sub create { my $self = shift; my %args = @_; my @command = ($helper_paths{createdb}); defined $args{copy_of} and push(@command, '-T', $args{copy_of}); # No need to pass the database name PGDATABASE will be set # if a 'dbname' connection parameter was provided $self->_run_command(command => [@command], error => 'error creating database'); return 1; } =head2 run_file Run the specified file on the db. After calling this method, STDOUT and STDERR output from the external utility which runs the file on the database are available as properties $db->stdout and $db->stderr respectively. Croaks on error. Returns true on success. Recognized arguments are: =over =item file Path to file to be run. This is a mandatory argument. =item vars A hash reference containing C-variables to be passed to the script being executed. Running: $dbadmin->run_file(file => '/tmp/pg.sql', vars => { schema => 'xyz' }); Is equivalent to starting the file C with the command \set schema xyz To undefine a variable, associate the variable name (hash key) with the value C. =item stdout_log Provided for legacy compatibility. Optional argument. The full path of a file to which STDOUT from the external psql utility will be appended. =item errlog Provided for legacy compatibility. Optional argument. The full path of a file to which STDERR from the external psql utility will be appended. =back =cut sub run_file { my ($self, %args) = @_; my $vars = $args{vars} // {}; $self->{stderr} = undef; $self->{stdout} = undef; croak 'Must specify file' unless defined $args{file}; croak 'Specified file does not exist' unless -e $args{file}; # Build command my @command = ($helper_paths{psql}, '--set=ON_ERROR_STOP=on', (map { ('-v', defined $vars->{$_} ? "$_=$vars->{$_}" : $_ ) } keys %$vars), '-f', $args{file}); my $result = $self->_run_command( command => [@command], errlog => $args{errlog}, stdout_log => $args{stdout_log}, error => "error running file '$args{file}'"); return $result; } =head2 backup Creates a database backup file. After calling this method, STDOUT and STDERR output from the external utility which runs the file on the database are available as properties $db->stdout and $db->stderr respectively. Unlinks the output file and croaks on error. Returns the full path of the file containining the backup. Accepted parameters: =over =item format The specified format, for example c for custom. Defaults to plain text. =item file Full path of the file to which the backup will be written. If the file does not exist, one will be created with umask 0600. If the file exists, it will be overwritten, but its permissions will not be changed. If undefined, a file will be created using File::Temp having umask 0600. =item tempdir The directory in which to write the backup file. Optional parameter. Uses File::Temp default if not defined. Ignored if file parameter is given. =item compress Optional parameter. Specifies the compression level to use and is passed to the underlying pg_dump command. Default is no compression. =back =cut sub backup { my ($self, %args) = @_; $self->{stderr} = undef; $self->{stdout} = undef; my $output_filename = $self->_generate_output_filename(%args); my @command = ($helper_paths{pg_dump}, '-f', $output_filename); defined $args{compress} and push(@command, '-Z', $args{compress}); defined $args{format} and push(@command, "-F$args{format}"); $self->_run_command(command => [@command], unlink => [$output_filename], error => 'error running pg_dump command'); return $output_filename; } =head2 backup_globals This creates a file containing a plain text dump of global (inter-db) objects, such as users and tablespaces. It uses pg_dumpall to do this. Being a plain text file, it can be restored using the run_file method. Unlinks the output file and croaks on error. Returns the full path of the file containining the backup. Accepted parameters: =over =item file Full path of the file to which the backup will be written. If the file does not exist, one will be created with umask 0600. If the file exists, it will be overwritten, but its permissions will not be changed. If undefined, a file will be created using File::Temp having umask 0600. =item tempdir The directory in which to write the backup file. Optional parameter. Uses File::Temp default if not defined. Ignored if file parameter is given. =back =cut sub backup_globals { my ($self, %args) = @_; $self->{stderr} = undef; $self->{stdout} = undef; local $ENV{PGPASSWORD} = $self->password if defined $self->password; my $output_filename = $self->_generate_output_filename(%args); my @command = ($helper_paths{pg_dumpall}, '-g', '-f', $output_filename); $self->_run_command(command => [@command], unlink => [$output_filename], error => 'error running pg_dumpall command'); return $output_filename; } =head2 restore Restores from a saved file. Must pass in the file name as a named argument. After calling this method, STDOUT and STDERR output from the external restore utility are available as properties $db->stdout and $db->stderr respectively. Croaks on error. Returns true on success. Recognized arguments are: =over =item file Path to file which will be restored to the database. Required. =item format The file format, for example c for custom. Defaults to plain text. =back =cut sub restore { my ($self, %args) = @_; $self->{stderr} = undef; $self->{stdout} = undef; croak 'Must specify file' unless defined $args{file}; croak 'Specified file does not exist' unless -e $args{file}; return $self->run_file(%args) if not defined $args{format} or $args{format} eq 'p'; # Build command options my @command = ($helper_paths{pg_restore}, '--verbose', '--exit-on-error'); defined $args{format} and push(@command, "-F$args{format}"); defined $self->connect_data->{dbname} and push(@command, '-d', $self->connect_data->{dbname}); push(@command, $args{file}); $self->_run_command(command => [@command], error => "error restoring from $args{file}"); return 1; } =head2 drop Drops the database. This is not recoverable. Croaks on error, returns true on success. =cut sub drop { my ($self) = @_; croak 'No db name of this object' unless $self->dbname; my @command = ($helper_paths{dropdb}); push(@command, $self->connect_data->{dbname}); $self->_run_command(command => [@command], error => 'error dropping database'); return 1; } =head2 is_ready Drops the database. This is not recoverable. Croaks on error, returns true on success. =cut sub is_ready { my ($self) = @_; croak 'No db name of this object' unless $self->dbname; my @command = ($helper_paths{pg_isready}); push(@command, $self->connect_data->{dbname}); $self->_run_command(command => [@command], error => 'error dropping database'); return 1; } =head1 CAPTURING This module uses C to run extenal commands and capture their output, which is made available through the C and C properties. This capturing does not work if Perl's standard C or C filehandles have been localized. In this situation, the localized filehandles are captured, but external system calls are not affected by the localization, so their output is sent to the original filehandles and is not captured. See the C documentation for more details. =head1 AUTHOR Chris Travers, C<< >> =head1 BUGS Please report any bugs or feature requests to C, or through the web interface at L. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes. =head1 SUPPORT You can find documentation for this module with the perldoc command. perldoc PGObject::Util::DBAdmin You can also look for information at: =over 4 =item * RT: CPAN's request tracker (report bugs here) L =item * AnnoCPAN: Annotated CPAN documentation L =item * CPAN Ratings L =item * Search CPAN L =back =head1 ACKNOWLEDGEMENTS =head1 LICENSE AND COPYRIGHT Copyright 2014-2020 Chris Travers. This program is distributed under the (Revised) BSD License: L Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Chris Travers's Organization nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =cut 1; # End of PGObject::Util::DBAdmin PGObject-Util-DBAdmin-1.6.1/MANIFEST0000644000175000017500000000106514141757620015133 0ustar erikerikChanges ignore.txt lib/PGObject/Util/DBAdmin.pm Makefile.PL MANIFEST This list of files README t/00.1-critic.t t/00.2-load.t t/01.1-dbtests.t t/01.2-backup_globals.t t/01.3-verify-helpers.t t/02-dbexceptions.t t/03-file_errors.t t/boilerplate.t t/data/an_existing_file t/data/backup.sqlc t/data/bad.sql t/data/schema.sql t/manifest.t t/perlcriticrc t/pod-coverage.t t/pod.t META.yml Module YAML meta-data (added by MakeMaker) META.json Module JSON meta-data (added by MakeMaker) PGObject-Util-DBAdmin-1.6.1/README0000644000175000017500000000574114123341763014664 0ustar erikerikPGObject-Util-DBAdmin This module provides a basic interface to command line utilities. With it you can create and drop databases, list databases, take and restore backups, and run sql files against databases. INSTALLATION To install this module, run the following commands: perl Makefile.PL make make test make install TESTING By default, tests which interact with a database are not run. To run the full test suite, set environment variable DB_TESTING=1. The database password may be set with environment variable PGPASSWORD. For example: DB_TESTING=1 PGPASSWORD=XXXXX make test Database tests are run using a database named `pgobject_test_db`, which will be dropped if it already exists. SUPPORT AND DOCUMENTATION After installing, you can find documentation for this module with the perldoc command. perldoc PGObject::Util::DBAdmin You can also look for information at: RT, CPAN's request tracker (report bugs here) http://rt.cpan.org/NoAuth/Bugs.html?Dist=PGObject-Util-DBAdmin AnnoCPAN, Annotated CPAN documentation http://annocpan.org/dist/PGObject-Util-DBAdmin CPAN Ratings http://cpanratings.perl.org/d/PGObject-Util-DBAdmin Search CPAN http://search.cpan.org/dist/PGObject-Util-DBAdmin/ GitHub source code repository (contribute patches here) https://github.com/ledgersmb/PGObject-Util-DBAdmin LICENSE AND COPYRIGHT Copyright (C) 2014-2019 Chris Travers This program is distributed under the (Revised) BSD License: L Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Chris Travers's Organization nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. PGObject-Util-DBAdmin-1.6.1/ignore.txt0000644000175000017500000000032414123341763016020 0ustar erikerikMakefile Makefile.old Build Build.bat META.* MYMETA.* .build/ _build/ cover_db/ blib/ inc/ .lwpcookies .last_cover_stats nytprof.out pod2htm*.tmp pm_to_blib PGObject-Util-DBAdmin-* PGObject-Util-DBAdmin-*.tar.gz PGObject-Util-DBAdmin-1.6.1/Makefile.PL0000644000175000017500000000252614123341763015754 0ustar erikerikuse 5.010; use strict; use warnings FATAL => 'all'; use ExtUtils::MakeMaker; WriteMakefile( NAME => 'PGObject::Util::DBAdmin', AUTHOR => q{Chris Travers }, VERSION_FROM => 'lib/PGObject/Util/DBAdmin.pm', ABSTRACT_FROM => 'lib/PGObject/Util/DBAdmin.pm', LICENSE => 'BSD', PL_FILES => {}, MIN_PERL_VERSION => 5.010, CONFIGURE_REQUIRES => { 'ExtUtils::MakeMaker' => 0, }, TEST_REQUIRES => { 'Test::More' => 0, 'Test::Exception' => 0, 'Perl::Critic' => 0, 'Perl::Critic::Policy::Modules::RequireExplicitInclusion' => 0, }, PREREQ_PM => { 'DBD::Pg' => 0, 'Capture::Tiny' => 0, 'DBI' => 0, 'Moo' => 0, 'Log::Any' => 0, 'Scope::Guard' => 0, 'namespace::clean' => 0, }, dist => { COMPRESS => 'gzip -9f', SUFFIX => 'gz', }, clean => { FILES => 'PGObject-Util-DBAdmin-*' }, META_MERGE => { 'meta-spec' => { version => 2 }, resources => { repository => { type => 'git', url => 'https://github.com/ledgersmb/PGObject-Util-DBAdmin.git', web => 'https://github.com/ledgersmb/PGObject-Util-DBAdmin', }, }, }, ); PGObject-Util-DBAdmin-1.6.1/META.yml0000664000175000017500000000161714141757620015260 0ustar erikerik--- abstract: 'PostgreSQL Database Management Facilities for PGObject' author: - 'Chris Travers ' build_requires: ExtUtils::MakeMaker: '0' Perl::Critic: '0' Perl::Critic::Policy::Modules::RequireExplicitInclusion: '0' Test::Exception: '0' Test::More: '0' configure_requires: ExtUtils::MakeMaker: '0' dynamic_config: 1 generated_by: 'ExtUtils::MakeMaker version 7.34, CPAN::Meta::Converter version 2.150010' license: bsd meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: '1.4' name: PGObject-Util-DBAdmin no_index: directory: - t - inc requires: Capture::Tiny: '0' DBD::Pg: '0' DBI: '0' Log::Any: '0' Moo: '0' Scope::Guard: '0' namespace::clean: '0' perl: '5.01' resources: repository: https://github.com/ledgersmb/PGObject-Util-DBAdmin.git version: v1.6.1 x_serialization_backend: 'CPAN::Meta::YAML version 0.018' PGObject-Util-DBAdmin-1.6.1/META.json0000664000175000017500000000315514141757620015427 0ustar erikerik{ "abstract" : "PostgreSQL Database Management Facilities for PGObject", "author" : [ "Chris Travers " ], "dynamic_config" : 1, "generated_by" : "ExtUtils::MakeMaker version 7.34, CPAN::Meta::Converter version 2.150010", "license" : [ "bsd" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : 2 }, "name" : "PGObject-Util-DBAdmin", "no_index" : { "directory" : [ "t", "inc" ] }, "prereqs" : { "build" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "configure" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "runtime" : { "requires" : { "Capture::Tiny" : "0", "DBD::Pg" : "0", "DBI" : "0", "Log::Any" : "0", "Moo" : "0", "Scope::Guard" : "0", "namespace::clean" : "0", "perl" : "5.01" } }, "test" : { "requires" : { "Perl::Critic" : "0", "Perl::Critic::Policy::Modules::RequireExplicitInclusion" : "0", "Test::Exception" : "0", "Test::More" : "0" } } }, "release_status" : "stable", "resources" : { "repository" : { "type" : "git", "url" : "https://github.com/ledgersmb/PGObject-Util-DBAdmin.git", "web" : "https://github.com/ledgersmb/PGObject-Util-DBAdmin" } }, "version" : "v1.6.1", "x_serialization_backend" : "JSON::PP version 4.02" } PGObject-Util-DBAdmin-1.6.1/Changes0000644000175000017500000001160714141757560015303 0ustar erikerikRevision history for PGObject-Util-DBAdmin 1.6.1 2021-11-07 * Fix syntax error 1.6.0 2021-11-07 * Add support for passing variables to 'psql' invocations * Sort keys in environment variable settings being logged * Add support for the 'pg_isready' tool 1.5.0 2021-09-25 * Don't parse the server version string; use the database handle's 'pg_server_version' property instead -- parsing the server version may return the wrong tuple if multiple are included 1.4.0 2020-10-25 * Add (debug) logging through Log::Any; each instance has a logger through the new `logger` attribute 1.3.0 2020-10-24 * Restore umask using Scope::Guard for maximum reliability * More meaningful error messages 1.2.3 2020-10-24 * Restore pre-1.2.0 compatibility by allowing a reference to be passed into the constructor/BUILDARGS 1.2.2 2020-10-23 * Fall back to dbname in 'connect_data' init_arg when no explicit 'dbname' init_arg is supplied. 1.2.1 2020-10-22 * Fix 'Odd number of elements in hash assignment' bug 1.2.0 2020-10-21 * Deprecate attributes 'username', 'password' and 'dbname' * Introduce new 'connect_data' attribute which can hold all the attributes supported by PostgreSQL as documented on https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-PARAMKEYWORDS 1.1.0 2020-09-21 * Add optional parameter to 'list_dbs' and 'server_version' 1.0.3 2019-09-29 * Run 'verify_helpers' test only in AUTHOR_TESTING mode as it requires the Pg client applications to be installed on testers (including cpantesters, which don't all have those) 1.0.2 2019-09-20 * Fix the MANIFEST listing non-existing files 1.0.1 2019-07-09 * Fix: the 'verify_helpers' API bleeds output through to the STDERR and STDOUT streams. 1.0.0 2019-07-08 * Extend API with 'verify_helpers' class method to allow users to assert whether the module can successfully run its helpers or not 0.131.0 2019-07-06 * Sanitize the environment before shelling out to external programs, because (a) that's the secure thing to do and (b) it breaks the called programs if the environment contains debugging settings 0.130.1 2018-06-05 * Correct typos in documentation 0.130.0 2018-04-21 * Backups use pg_dump and pg_dumpall `-f` option, not stdout capture * Document effect of localizing filehandles on output capture * Add `compress` parameter to backup() method * Set DB_TESTING=1 to run file tests as they require postgreSQL utilities * In Makefile.PL, correctly classify test deps as TEST_REQUIRES 0.120.0 2018-03-27 * Documentation fixes * Don't use shell to execute external commands, blocks command injection * Trap shell errors running external commands * Test exit code after running external commands * Don't attempt to parse stderr from external commands for errors * External command stdout/stderr available via object property * Default to temporary directory provided by File::Temp * Respect method parameters if defined (previously only if true) * Add further tests, including Perl::Critic * Create backup output files with umask 0600 * Delete incomplete backup files after error * Raise exceptions with croak/carp rather than die/warn external psql command now run with `--set=ON_ERROR_STOP=on` external pg_restore command now run with `--exit-on-error` * Bump minimum perl version to 5.10 0.110.0 2017-11-21 * Correctly invoke 'pg_dump' (it doesn't recognise a '-d' option) * Remove tabs from sources * Fix #6: 'host' and 'port' arguments not used in 'connect()' 0.100.0 2016-12-17 * Publish 0.10 as 0.100; CPAN considers 0.09 equal to 0.090, which is higher than 0.10.0 (which is 0.010_000) 0.10.0 2016-12-17 * Removed MYMETA.* (rt.cpan.org#109062) * Correct spelling errors reported by Robert James Clay (jame@rocasa.us) * Correct copyright years (rt.cpan.org#117202 and #10) 0.09 2016-07-18 * Fixed handling of &'s in db names 0.08 2016-02-11 * Added ability to pass connection parameters to connect() 0.07 2015-07-16 * Fixed handling of connection when connection fails 0.06 2014-09-18 * Fixed support for remote hosts. 0.05 2014-09-14 * Added backup of globals 0.04 2014-09-14 * Additional tests * Fixing packaging bugs * Adding server_version api 0.03 2014-09-13 * Better handling of auth environment variables so they don't always clobber * Fixes to exception handling * More tests 0.02 2014-09-12 * Better error handling of external programs, using Tiny::Capture to process external stderr 0.01 2014-09-11 * First version, released on an unsuspecting world.