File Coverage

blib/lib/PGObject/Util/DBAdmin.pm
Criterion Covered Total %
statement 32 178 17.9
branch 0 64 0.0
condition 0 24 0.0
subroutine 11 35 31.4
pod 11 11 100.0
total 54 312 17.3


line stmt bran cond sub pod time code
1             package PGObject::Util::DBAdmin;
2              
3 6     6   454485 use 5.010; # Uses // defined-or operator
  6         83  
4 6     6   53 use strict;
  6         13  
  6         152  
5 6     6   34 use warnings FATAL => 'all';
  6         10  
  6         274  
6              
7 6     6   3708 use Capture::Tiny 'capture';
  6         129377  
  6         368  
8 6     6   50 use Carp;
  6         12  
  6         359  
9 6     6   9625 use DBI;
  6         108238  
  6         377  
10 6     6   58 use File::Temp;
  6         11  
  6         453  
11 6     6   3651 use Log::Any;
  6         50638  
  6         33  
12 6     6   3000 use Scope::Guard qw(guard);
  6         2786  
  6         336  
13              
14 6     6   3188 use Moo;
  6         69949  
  6         33  
15 6     6   12196 use namespace::clean;
  6         70086  
  6         43  
16              
17             =head1 NAME
18              
19             PGObject::Util::DBAdmin - PostgreSQL Database Management Facilities for
20             PGObject
21              
22             =head1 VERSION
23              
24             version 1.4.0
25              
26             =cut
27              
28             our $VERSION = '1.4.0';
29              
30              
31             =head1 SYNOPSIS
32              
33             This module provides an interface to the basic Postgres db manipulation
34             utilities.
35              
36             my $db = PGObject::Util::DBAdmin->new(
37             connect_data => {
38             user => 'postgres',
39             password => 'mypassword',
40             host => 'localhost',
41             port => '5432',
42             dbname => 'mydb'
43             }
44             );
45              
46             my @dbnames = $db->list_dbs(); # like psql -l
47              
48             $db->create(); # createdb
49             $db->run_file(file => 'sql/initial_schema.sql'); # psql -f
50              
51             my $filename = $db->backup(format => 'c'); # pg_dump -Fc
52              
53             my $db2 = PGObject::Util::DBAdmin->new($db->export, (dbname => 'otherdb'));
54              
55             my $db3 = PGObject::Util::DBAdmin->new(
56             connect_data => {
57             service => 'zephyr',
58             sslmode => 'require',
59             sslkey => "$HOME/.postgresql/postgresql.key",
60             sslcert => "$HOME/.postgresql/postgresql.crt",
61             sslpassword => 'your-sslpassword',
62             }
63             );
64              
65              
66             =head1 PROPERTIES
67              
68             =head2 connect_data
69              
70             Contains a hash with connection parameters; see L<the PostgreSQL
71             documentation|https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-PARAMKEYWORDS>
72             for supported parameters.
73              
74             The usual parameters are:
75              
76             =over
77              
78             =item * user
79              
80             =item * password
81              
82             =item * dbname
83              
84             =item * host
85              
86             =item * port
87              
88             =back
89              
90             Please note that the key C<requiressl> is deprecated in favor of
91             C<sslmode> and isn't supported.
92              
93             =cut
94              
95             # Not supported
96             # PGSERVICEFILE: (because no connect string equiv)
97             # PGREQUIRESSL: deprecated
98             my %connkey_env = qw(
99             host PGHOST
100             hostaddr PGHOSTADDR
101             dbname PGDATABASE
102             user PGUSER
103             password PGPASSWORD
104             passfile PGPASSFILE
105             channel_binding PGCHANNELBINDING
106             service PGSERVICE
107             options PGOPTIONS
108             sslmode PGSSLMODE
109             sslcompression PGSSLCOMPRESSION
110             sslcert PGSSLCERT
111             sslkey PGSSLKEY
112             sslrootcert PGSSLROOTCERT
113             sslcrl PGSSLCRL
114             requirepeer PGREQUIREPEER
115             ssl_min_protocol_version PGSSLMINPROTOCOLVERSION
116             ssl_max_protocol_version PGSSLMAXPROTOCOLVERSION
117             gssencmode PGGSSENCMODE
118             krbsrvname PGKRBSRVNAME
119             gsslib PGGSSLIB
120             connect_timeout PGCONNECT_TIMEOUT
121             client_encoding PGCLIENTENCODING
122             target_session_attrs PGTARGETSESSIONATTRS
123             );
124             my @connstr_keys = ((grep { not ($_ eq 'user' or $_ eq 'password') }
125             keys %connkey_env),
126             qw(application_name fallback_application_name
127             keepalives keepalives_idle keepalives_interval
128             keepalives_count tcp_user_timeout replication sslpassword),
129             );
130              
131             sub _connect_data_env {
132 0     0     my ($connect_data) = @_;
133 0           my @keys = grep { exists $connkey_env{$_}
134 0 0         and defined $connect_data->{$_} } keys %$connect_data;
135 0           return map { $connkey_env{$_} => $connect_data->{$_} } @keys;
  0            
136             }
137              
138             sub _connect_data_str {
139 0     0     my ($connect_data) = @_;
140 0           my @keys = grep { defined $connect_data->{$_} } @connstr_keys;
  0            
141             return join(';', map {
142 0           my $val = $connect_data->{$_};
  0            
143 0           $val =~ s/\\/\\\\/g;
144 0           $val =~ s/'/\\'/g;
145 0           "$_='$val'"; } @keys );
146             }
147              
148             has connect_data => (is => 'ro');
149              
150             =head2 username (deprecated)
151              
152             The username used to authenticate with the PostgreSQL server.
153              
154             =cut
155              
156             has username => (is => 'ro');
157              
158             =head2 password (deprecated)
159              
160             The password used to authenticate with the PostgreSQL server.
161              
162             =cut
163              
164             has password => (is => 'ro');
165              
166             =head2 host (deprecated)
167              
168             In PostgreSQL, this can refer to the hostname or the absolute path to the
169             directory where the UNIX sockets are set up.
170              
171             =cut
172              
173             has host => (is => 'ro');
174              
175             =head2 port (deprecated)
176              
177             Default '5432'
178              
179             =cut
180              
181             has port => (is => 'ro');
182              
183             =head2 dbname (deprecated)
184              
185             The database name to create or connect to.
186              
187             =cut
188              
189             has dbname => (is => 'ro');
190              
191             =head2 stderr
192              
193             When applicable, the stderr output captured from any external commands (for
194             example createdb or pg_restore) run during the previous method call. See
195             notes in L</"CAPTURING">.
196              
197             =cut
198              
199             has stderr => (is => 'ro');
200              
201             =head2 stdout
202              
203             When applicable, the stdout output captured from any external commands (for
204             example createdb or pg_restore) run during the previous method call. See
205             notes in L</"CAPTURING">.
206              
207             =cut
208              
209             has stdout => (is => 'ro');
210              
211             =head2 logger
212              
213             Provides a reference to the logger associated with the current instance. The
214             logger uses C<ref $self> as its category, eliminating the need to create
215             new loggers when deriving from this class.
216              
217             If you want to override the logger-instantiation behaviour, please implement
218             the C<_build_logger> builder method in your derived class.
219              
220             =cut
221              
222             has logger => (is => 'ro', lazy => 1, builder => '_build_logger');
223              
224             sub _build_logger {
225 0     0     return Log::Any->get_logger(category => ref $_[0]);
226             }
227              
228              
229             our %helpers =
230             (
231             create => [ qw/createdb/ ],
232             run_file => [ qw/psql/ ],
233             backup => [ qw/pg_dump/ ],
234             backup_globals => [ qw/pg_dumpall/ ],
235             restore => [ qw/pg_restore psql/ ],
236             drop => [ qw/dropdb/ ],
237             );
238              
239             =head1 GLOBAL VARIABLES
240              
241              
242             =head2 %helper_paths
243              
244             This hash variable contains as its keys the names of the PostgreSQL helper
245             executables C<psql>, C<dropdb>, C<pg_dump>, etc. The values contain the
246             paths at which the executables to be run are located. The default values
247             are the names of the executables only, allowing them to be looked up in
248             C<$PATH>.
249              
250             Modification of the values in this variable are the strict realm of
251             I<applications>. Libraries using this library should defer potential
252             required modifications to the applications based upon them.
253              
254             =cut
255              
256             our %helper_paths =
257             (
258             psql => 'psql',
259             dropdb => 'dropdb',
260             createdb => 'createdb',
261             pg_dump => 'pg_dump',
262             pg_dumpall => 'pg_dumpall',
263             pg_restore => 'pg_restore',
264             );
265              
266             sub _run_with_env {
267 0     0     my %args = @_;
268 0           my $env = $args{env};
269              
270             local %ENV = (
271             # Note that we're intentionally *not* passing
272             # PERL5LIB & PERL5OPT into the environment here!
273             # doing so prevents the system settings to be used, which
274             # we *do* want. If we don't, hopefully, that's coded into
275             # the executables themselves.
276             # Before using this whitelisting, coverage tests in LedgerSMB
277             # would break on the bleeding through this caused.
278             HOME => $ENV{HOME},
279             PATH => $ENV{PATH},
280 0   0       %{$env // {}},
  0            
281             );
282              
283 0           return system @{$args{command}};
  0            
284             }
285              
286             sub _run_command {
287 0     0     my ($self, %args) = @_;
288 0           my $exit_code;
289             my %env = (
290             # lowest priority: existing environment variables
291 0 0         (map { $ENV{$_} ? ($_ => $ENV{$_}) : () }
292             qw(PGUSER PGPASSWORD PGHOST PGPORT PGDATABASE PGSERVICE)),
293             # overruled by middle priority: object connection parameters
294             _connect_data_env($self->connect_data),
295             # overruled by highest priority: specified environment
296 0 0         ($args{env} ? %{$args{env}} : ()),
  0            
297             );
298             $self->logger->debugf(
299             sub {
300             return 'Running with environment: '
301 0     0     . join(' ', map { qq|$_="$env{$_}"| } keys %env );
  0            
302 0           });
303              
304             # Any files created should be accessible only by the current user
305 0           my $original_umask = umask 0077;
306             {
307 0     0     my $guard = guard { umask $original_umask; };
  0            
  0            
308              
309             ($self->{stdout}, $self->{stderr}, $exit_code) = capture {
310 0     0     _run_with_env(%args, env => \%env);
311 0           };
312 0 0 0       if(defined ($args{errlog} // $args{stdout_log})) {
313 0           $self->_write_log_files(%args);
314             }
315             }
316              
317 0 0         if ($exit_code != 0) {
318 0           for my $filename (@{$args{unlink}}) {
  0            
319 0 0         unlink $filename or carp "error unlinking '$filename': $!";
320             }
321 0           my $command = join( ' ', map { "'$_'" } @{$args{command}} );
  0            
  0            
322 0           my $err;
323 0 0         if ($? == -1) {
    0          
324 0           $err = "$!";
325             }
326             elsif ($? & 127) {
327 0           $err = sprintf('died with signal %d', ($? & 127));
328             }
329             else {
330 0           $err = sprintf('exited with code %d', ($? >> 8));
331             }
332 0           croak "$args{error}; (command: $command): $err";
333             }
334 0           return 1;
335             }
336              
337              
338             sub _generate_output_filename {
339 0     0     my ($self, %args) = @_;
340              
341             # If caller has supplied a file path, use that
342             # rather than generating our own temp file.
343 0 0         defined $args{file} and return $args{file};
344              
345 0           my %file_options = (UNLINK => 0);
346              
347 0 0         if(defined $args{tempdir}) {
348             -d $args{tempdir}
349 0 0         or croak "directory $args{tempdir} does not exist or is not a directory";
350 0           $file_options{DIR} = $args{tempdir};
351             }
352              
353             # File::Temp creates files with permissions 0600
354 0 0         my $fh = File::Temp->new(%file_options)
355             or croak "could not create temp file: $@, $!";
356              
357 0           return $fh->filename;
358             }
359              
360              
361             sub _write_log_files {
362 0     0     my ($self, %args) = @_;
363              
364             defined $args{stdout_log} and $self->_append_to_file(
365             $args{stdout_log},
366             $self->{stdout},
367 0 0         );
368              
369             defined $args{errlog} and $self->_append_to_file(
370             $args{errlog},
371             $self->{stderr},
372 0 0         );
373              
374 0           return;
375             }
376              
377              
378             sub _append_to_file {
379 0     0     my ($self, $filename, $data) = @_;
380              
381 0 0         open(my $fh, '>>', $filename)
382             or croak "couldn't open file $filename for appending $!";
383              
384 0 0 0       print $fh ($data // '')
385             or croak "failed writing to file $!";
386              
387 0 0         close $fh
388             or croak "failed closing file $filename $!";
389              
390 0           return;
391             }
392              
393              
394              
395             =head1 SUBROUTINES/METHODS
396              
397             =head2 new
398              
399             Creates a new db admin object for manipulating databases.
400              
401             =head2 BUILDARGS
402              
403             Compensates for the legacy invocation with the C<username>, C<password>,
404             C<host>, C<port> and C<dbname> parameters.
405              
406             =head2 verify_helpers( [ helpers => [...]], [operations => [...]])
407              
408             Verifies ability to execute (external) helper applications by
409             method name (through the C<operations> argument) or by external helper
410             name (through the C<helpers> argument). Returns a hash ref with each
411             key being the name of a helper application (see C<helpers> below) with
412             the values being a boolean indicating whether or not the helper can be
413             successfully executed.
414              
415             Valid values in the array referenced by the C<operations> parameter are
416             C<create>, C<run_file>, C<backup>, C<backup_globals>, C<restore> and
417             C<drop>; the methods this module implements with the help of external
418             helper programs. (Other values may be passed, but unsupported values
419             aren't included in the return value.)
420              
421             Valid values in the array referenced by the C<helpers> parameter are the
422             names of the PostgreSQL helper programs C<createdb>, C<dropdb>, C<pg_dump>,
423             C<pg_dumpall>, C<pg_restore> and C<psql>. (Other values may be passed, but
424             unsupported values will not be included in the return value.)
425              
426             When no arguments are passed, all helpers will be tested.
427              
428             Note: C<verify_helpers> is a class method, meaning it wants to be called
429             as C<PGObject::Util::DBAdmin->verify_helpers()>.
430              
431             =cut
432              
433             around 'BUILDARGS' => sub {
434             my ($orig, $class, @args) = @_;
435              
436             ## 1.1.0 compatibility code (allow a reference to be passed in)
437             my %args = (@args == 1 and ref $args[0]) ? (%{$args[0]}) : (@args);
438              
439             # deprecated field support code block
440             if (exists $args{connect_data}) {
441             # Work-around for 'export' creating the expectation that
442             # parameters may be overridable; I've observed the pattern
443             # ...->new($db->export, (dbname => 'newdb'))
444             # which we "solve" by hacking the dbname arg into the connect_data
445             # Don't overwrite connect_data, because it may be used elsewhere...
446             $args{connect_data} = {
447             %{$args{connect_data}},
448             dbname => ($args{dbname} // $args{connect_data}->{dbname})
449             };
450              
451             # Now for legacy purposes hack the connection parameters into
452             # connect_data
453             $args{username} = $args{connect_data}->{user};
454             $args{$_} = $args{connect_data}->{$_} for (qw(password dbname
455             host port));
456             }
457             else {
458             $args{connect_data} = {};
459             $args{connect_data}->{user} = $args{username};
460             $args{connect_data}->{password} = $args{password};
461             $args{connect_data}->{dbname} = $args{dbname};
462             $args{connect_data}->{host} = $args{host};
463             $args{connect_data}->{port} = $args{port};
464             }
465             return $class->$orig(%args);
466             };
467              
468              
469              
470              
471             sub _run_capturing_output {
472 0     0     my @args = @_;
473 0     0     my ($stdout, $stderr, $exitcode) = capture { _run_with_env(@args); };
  0            
474              
475 0           return $exitcode;
476             }
477              
478             sub verify_helpers {
479 0     0 1   my ($class, %args) = @_;
480              
481             my @helpers = (
482 0   0       @{$args{helpers} // []},
483 0   0       map { @{$helpers{$_} // []} } @{$args{operations} // []}
  0   0        
  0            
  0            
484             );
485 0 0         if (not @helpers) {
486 0           @helpers = keys %helper_paths;
487             }
488             return {
489             map {
490 0           $_ => not _run_capturing_output(command =>
491 0           [ $helper_paths{$_} , '--help' ])
492             } @helpers
493             };
494             }
495              
496              
497             =head2 export
498              
499             Exports the database parameters as a list so it can be used to create another
500             object.
501              
502             =cut
503              
504             sub export {
505 0     0 1   my $self = shift;
506 0           return ( connect_data => $self->connect_data );
507             }
508              
509             =head2 connect($options)
510              
511             Connects to the database using DBI and returns a database connection.
512              
513             Connection options may be specified in the $options hashref.
514              
515             =cut
516              
517             sub connect {
518 0     0 1   my ($self, $options) = @_;
519              
520 0           my $connect = _connect_data_str($self->connect_data);
521             my $dbh = DBI->connect(
522             'dbi:Pg:' . $connect,
523             $self->connect_data->{user} // '', # suppress use of DBI_USER
524 0 0 0       $self->connect_data->{password} // '',# suppress use of DBI_PASS
      0        
525             $options
526             ) or croak 'Could not connect to database: ' . $DBI::errstr;
527              
528 0           return $dbh;
529             }
530              
531             =head2 server_version([$dbname])
532              
533             Returns a version string (like 9.1.4) for PostgreSQL. Croaks on error.
534              
535             When a database name is specified, uses that database to connect to,
536             using the credentials specified in the instance.
537              
538             If no database name is specified, 'template1' is used.
539              
540             =cut
541              
542             sub server_version {
543 0     0 1   my $self = shift @_;
544 0   0       my $dbname = (shift @_) || 'template1';
545 0           my $version =
546             __PACKAGE__->new($self->export, (dbname => $dbname)
547             )->connect->selectrow_array('SELECT version()');
548 0 0         my ($retval) = $version =~ /(\d+\.\d+\.\d+)/
549             or croak 'failed to extract version string';
550 0           return $retval;
551             }
552              
553              
554             =head2 list_dbs([$dbname])
555              
556             Returns a list of db names.
557              
558             When a database name is specified, uses that database to connect to,
559             using the credentials specified in the instance.
560              
561             If no database name is specified, 'template1' is used.
562              
563             =cut
564              
565             sub list_dbs {
566 0     0 1   my $self = shift;
567 0   0       my $dbname = (shift @_) || 'template1';
568              
569 0           return map { $_->[0] }
570 0           @{ __PACKAGE__->new($self->export, (dbname => $dbname)
  0            
571             )->connect->selectall_arrayref(
572             'SELECT datname from pg_database order by datname'
573             ) };
574             }
575              
576             =head2 create
577              
578             Creates a new database.
579              
580             Croaks on error, returns true on success.
581              
582             Supported arguments:
583              
584             =over
585              
586             =item copy_of
587              
588             Creates the new database as a copy of the specified one (using it as
589             a template). Optional parameter. Default is to create a database
590             without a template.
591              
592             =back
593              
594             =cut
595              
596             sub create {
597 0     0 1   my $self = shift;
598 0           my %args = @_;
599              
600 0           my @command = ($helper_paths{createdb});
601 0 0         defined $args{copy_of} and push(@command, '-T', $args{copy_of});
602             # No need to pass the database name PGDATABASE will be set
603             # if a 'dbname' connection parameter was provided
604              
605 0           $self->_run_command(command => [@command],
606             error => 'error creating database');
607              
608 0           return 1;
609             }
610              
611              
612             =head2 run_file
613              
614             Run the specified file on the db.
615              
616             After calling this method, STDOUT and STDERR output from the external
617             utility which runs the file on the database are available as properties
618             $db->stdout and $db->stderr respectively.
619              
620             Croaks on error. Returns true on success.
621              
622             Recognized arguments are:
623              
624             =over
625              
626             =item file
627              
628             Path to file to be run. This is a mandatory argument.
629              
630             =item stdout_log
631              
632             Provided for legacy compatibility. Optional argument. The full path of
633             a file to which STDOUT from the external psql utility will be appended.
634              
635             =item errlog
636              
637             Provided for legacy compatibility. Optional argument. The full path of
638             a file to which STDERR from the external psql utility will be appended.
639              
640             =back
641              
642             =cut
643              
644             sub run_file {
645 0     0 1   my ($self, %args) = @_;
646 0           $self->{stderr} = undef;
647 0           $self->{stdout} = undef;
648              
649 0 0         croak 'Must specify file' unless defined $args{file};
650 0 0         croak 'Specified file does not exist' unless -e $args{file};
651              
652             # Build command
653             my @command =
654 0           ($helper_paths{psql}, '--set=ON_ERROR_STOP=on', '-f', $args{file});
655              
656             my $result = $self->_run_command(
657             command => [@command],
658             errlog => $args{errlog},
659             stdout_log => $args{stdout_log},
660 0           error => "error running file '$args{file}'");
661              
662 0           return $result;
663             }
664              
665              
666             =head2 backup
667              
668             Creates a database backup file.
669              
670             After calling this method, STDOUT and STDERR output from the external
671             utility which runs the file on the database are available as properties
672             $db->stdout and $db->stderr respectively.
673              
674             Unlinks the output file and croaks on error.
675              
676             Returns the full path of the file containining the backup.
677              
678             Accepted parameters:
679              
680             =over
681              
682             =item format
683              
684             The specified format, for example c for custom. Defaults to plain text.
685              
686             =item file
687              
688             Full path of the file to which the backup will be written. If the file
689             does not exist, one will be created with umask 0600. If the file exists,
690             it will be overwritten, but its permissions will not be changed.
691              
692             If undefined, a file will be created using File::Temp having umask 0600.
693              
694             =item tempdir
695              
696             The directory in which to write the backup file. Optional parameter. Uses
697             File::Temp default if not defined. Ignored if file parameter is given.
698              
699             =item compress
700              
701             Optional parameter. Specifies the compression level to use and is passed to
702             the underlying pg_dump command. Default is no compression.
703              
704             =back
705              
706             =cut
707              
708             sub backup {
709 0     0 1   my ($self, %args) = @_;
710 0           $self->{stderr} = undef;
711 0           $self->{stdout} = undef;
712              
713 0           my $output_filename = $self->_generate_output_filename(%args);
714              
715 0           my @command = ($helper_paths{pg_dump}, '-f', $output_filename);
716 0 0         defined $args{compress} and push(@command, '-Z', $args{compress});
717 0 0         defined $args{format} and push(@command, "-F$args{format}");
718              
719 0           $self->_run_command(command => [@command],
720             unlink => [$output_filename],
721             error => 'error running pg_dump command');
722              
723 0           return $output_filename;
724             }
725              
726              
727             =head2 backup_globals
728              
729             This creates a file containing a plain text dump of global (inter-db)
730             objects, such as users and tablespaces. It uses pg_dumpall to do this.
731              
732             Being a plain text file, it can be restored using the run_file method.
733              
734             Unlinks the output file and croaks on error.
735              
736             Returns the full path of the file containining the backup.
737              
738             Accepted parameters:
739              
740             =over
741              
742             =item file
743              
744             Full path of the file to which the backup will be written. If the file
745             does not exist, one will be created with umask 0600. If the file exists,
746             it will be overwritten, but its permissions will not be changed.
747              
748             If undefined, a file will be created using File::Temp having umask 0600.
749              
750             =item tempdir
751              
752             The directory in which to write the backup file. Optional parameter. Uses
753             File::Temp default if not defined. Ignored if file parameter is given.
754              
755             =back
756              
757             =cut
758              
759             sub backup_globals {
760 0     0 1   my ($self, %args) = @_;
761 0           $self->{stderr} = undef;
762 0           $self->{stdout} = undef;
763              
764 0 0         local $ENV{PGPASSWORD} = $self->password if defined $self->password;
765 0           my $output_filename = $self->_generate_output_filename(%args);
766              
767 0           my @command = ($helper_paths{pg_dumpall}, '-g', '-f', $output_filename);
768              
769 0           $self->_run_command(command => [@command],
770             unlink => [$output_filename],
771             error => 'error running pg_dumpall command');
772              
773 0           return $output_filename;
774             }
775              
776              
777             =head2 restore
778              
779             Restores from a saved file. Must pass in the file name as a named argument.
780              
781             After calling this method, STDOUT and STDERR output from the external
782             restore utility are available as properties $db->stdout and $db->stderr
783             respectively.
784              
785             Croaks on error. Returns true on success.
786              
787             Recognized arguments are:
788              
789             =over
790              
791             =item file
792              
793             Path to file which will be restored to the database. Required.
794              
795             =item format
796              
797             The file format, for example c for custom. Defaults to plain text.
798              
799             =back
800              
801             =cut
802              
803             sub restore {
804 0     0 1   my ($self, %args) = @_;
805 0           $self->{stderr} = undef;
806 0           $self->{stdout} = undef;
807              
808 0 0         croak 'Must specify file' unless defined $args{file};
809 0 0         croak 'Specified file does not exist' unless -e $args{file};
810              
811             return $self->run_file(%args)
812 0 0 0       if not defined $args{format} or $args{format} eq 'p';
813              
814             # Build command options
815 0           my @command = ($helper_paths{pg_restore}, '--verbose', '--exit-on-error');
816 0 0         defined $args{format} and push(@command, "-F$args{format}");
817             defined $self->connect_data->{dbname} and
818 0 0         push(@command, '-d', $self->connect_data->{dbname});
819 0           push(@command, $args{file});
820              
821 0           $self->_run_command(command => [@command],
822             error => "error restoring from $args{file}");
823              
824 0           return 1;
825             }
826              
827              
828             =head2 drop
829              
830             Drops the database. This is not recoverable. Croaks on error, returns
831             true on success.
832              
833             =cut
834              
835             sub drop {
836 0     0 1   my ($self) = @_;
837              
838 0 0         croak 'No db name of this object' unless $self->dbname;
839              
840 0           my @command = ($helper_paths{dropdb});
841 0           push(@command, $self->connect_data->{dbname});
842              
843 0           $self->_run_command(command => [@command],
844             error => 'error dropping database');
845              
846 0           return 1;
847             }
848              
849              
850             =head1 CAPTURING
851              
852             This module uses C<Capture::Tiny> to run extenal commands and capture their
853             output, which is made available through the C<stderr> and C<stdout>
854             properties.
855              
856             This capturing does not work if Perl's standard C<STDOUT> or
857             C<STDERR> filehandles have been localized. In this situation, the localized
858             filehandles are captured, but external system calls are not
859             affected by the localization, so their output is sent to the original
860             filehandles and is not captured.
861              
862             See the C<Capture::Tiny> documentation for more details.
863              
864             =head1 AUTHOR
865              
866             Chris Travers, C<< <chris at efficito.com> >>
867              
868             =head1 BUGS
869              
870             Please report any bugs or feature requests to C<bug-pgobject-util-dbadmin at rt.cpan.org>, or through
871             the web interface at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=PGObject-Util-DBAdmin>. I will be notified, and then you'll
872             automatically be notified of progress on your bug as I make changes.
873              
874              
875              
876              
877             =head1 SUPPORT
878              
879             You can find documentation for this module with the perldoc command.
880              
881             perldoc PGObject::Util::DBAdmin
882              
883              
884             You can also look for information at:
885              
886             =over 4
887              
888             =item * RT: CPAN's request tracker (report bugs here)
889              
890             L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=PGObject-Util-DBAdmin>
891              
892             =item * AnnoCPAN: Annotated CPAN documentation
893              
894             L<http://annocpan.org/dist/PGObject-Util-DBAdmin>
895              
896             =item * CPAN Ratings
897              
898             L<http://cpanratings.perl.org/d/PGObject-Util-DBAdmin>
899              
900             =item * Search CPAN
901              
902             L<http://search.cpan.org/dist/PGObject-Util-DBAdmin/>
903              
904             =back
905              
906              
907             =head1 ACKNOWLEDGEMENTS
908              
909              
910             =head1 LICENSE AND COPYRIGHT
911              
912             Copyright 2014-2020 Chris Travers.
913              
914             This program is distributed under the (Revised) BSD License:
915             L<http://www.opensource.org/licenses/BSD-3-Clause>
916              
917             Redistribution and use in source and binary forms, with or without
918             modification, are permitted provided that the following conditions
919             are met:
920              
921             * Redistributions of source code must retain the above copyright
922             notice, this list of conditions and the following disclaimer.
923              
924             * Redistributions in binary form must reproduce the above copyright
925             notice, this list of conditions and the following disclaimer in the
926             documentation and/or other materials provided with the distribution.
927              
928             * Neither the name of Chris Travers's Organization
929             nor the names of its contributors may be used to endorse or promote
930             products derived from this software without specific prior written
931             permission.
932              
933             THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
934             "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
935             LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
936             A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
937             OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
938             SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
939             LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
940             DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
941             THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
942             (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
943             OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
944              
945              
946             =cut
947              
948             1; # End of PGObject::Util::DBAdmin