File Coverage

blib/lib/Module/Build/Database/PostgreSQL.pm
Criterion Covered Total %
statement 36 306 11.7
branch 0 96 0.0
condition 0 47 0.0
subroutine 12 44 27.2
pod 0 6 0.0
total 48 499 9.6


line stmt bran cond sub pod time code
1             =head1 NAME
2              
3             Module::Build::Database::PostgreSQL - PostgreSQL implementation for MBD
4              
5             =head1 SYNOPSIS
6              
7             In Build.PL :
8              
9             my $builder = Module::Build::Database->new(
10             database_type => "PostgreSQL",
11             database_options => {
12             name => "my_database_name",
13             schema => "my_schema_name",
14             # Extra items for scratch databases :
15             append_to_conf => "text to add to postgresql.conf",
16             after_create => q[create schema audit;],
17             },
18             database_extensions => {
19             postgis => { schema => "public", },
20             # directory with postgis.sql and spatial_ref_sys.sql
21             postgis_base => '/usr/local/share/postgresql/contrib'
22             },
23             );
24              
25             =head1 DESCRIPTION
26              
27             Postgres driver for L.
28              
29             =head1 OPTIONS
30              
31             All of the options above may be changed via the Module::Build option
32             handling, e.g.
33              
34             perl Build.PL --database_options name=my_name
35             perl Build.PL --postgis_base=/usr/local/share/postgresql/contrib
36              
37             The options are as follows ;
38              
39             =over 4
40              
41             =item database_options
42              
43             =over 4
44              
45             =item name
46              
47             the name of the database (i.e. 'create database $name')
48              
49             =item schema
50              
51             the name of the schema to be managed by MBD
52              
53             =item append_to_conf
54              
55             extra options to append to C before starting test instances of postgres
56              
57             =item after_create
58              
59             extra SQL to run after running a 'create database' statement. Note that this will be run in several
60             different situations :
61              
62             =over 4
63              
64             =item 1.
65              
66             during a L (creating a test db)
67              
68             =item 2.
69              
70             during a L (also creating a test db)
71              
72             =item 3.
73              
74             during an initial L; when the target database does not yet exist.
75              
76             =back
77              
78             An example of using the after_create statement would be to create a second schema which
79             will not be managed by MBD, but on which the MBD-managed schema depends.
80              
81             =back
82              
83             =item database_extension
84              
85             To specify a server side procedural language you can use the C -E C
86             option, like so:
87              
88             my $builder = Module::Build::Database->new(
89             database_extension => {
90             languages => [ 'plperl', 'pltcl' ],
91             },
92             );
93              
94             Trying to create languages to a patch will not work because they not stored in the main schema and will
95             not be included in C when you run C.
96              
97             This is also similar to
98              
99             after_create => 'create extension ...',
100              
101             except it is executed on B L meaning you can use this to add extensions to
102             existing database deployments.
103              
104             =item postgis_base
105              
106             Specify the directory containing postgis.sql and spatial_ref_sys.sql. If specified these SQL files will be loaded so that
107             you can use PostGIS in your database.
108              
109             =item leave_running
110              
111             If set to true, and if you are not using a persistent scratch database (see next option), then the scratch database will
112             not be stopped and torn down after running C or C.
113              
114             =item scratch_database
115              
116             You can use this option to specify the connection settings for a persistent scratch or temporary database instance, used by
117             the C and C to test schema. B: the C and C
118             will drop and re-create databases on the scratch instance with the same name as the database on your production instance so
119             it is I important that if you use a persistent scratch database that it be dedicated to that task.
120              
121             my $builder = Module::Build::Database->new(
122             scratch_database => {
123             PGHOST => 'databasehost',
124             PGPORT => '5555',
125             PGUSER => 'dbuser',
126             },
127             );
128              
129             If you specify any one of these keys for this option (C, C, C) then MBD will use a persistent
130             scratch database. Any missing values will use the default.
131              
132             You can also specify these settings using environment variables:
133              
134             % export MBD_SCRATCH_PGHOST=databasehost
135             % export MBD_SCRATCH_PGPORT=5555
136             % export MBD_SCRATCH_PGUSER=dbuser
137              
138             By default this module will create its own scratch PostgreSQL instance that uses unix domain sockets for communication
139             each time it needs one when you use the C or C commands. Situations where you might
140             need to use a persistent scratch database:
141              
142             =over 4
143              
144             =item 1.
145              
146             The server and server binaries are hosted on a system different to the one that you are doing development
147              
148             =item 2.
149              
150             You are using MBD on Windows where unix domain sockets are not available
151              
152             =back
153              
154             =back
155              
156             =head1 NOTES
157              
158             The environment variables understood by C:
159             C, C and C will be used when
160             connecting to a live database (for L and
161             L). C will be ignored;
162             the name of the database should be specified in
163             Build.PL instead.
164              
165             =cut
166              
167             package Module::Build::Database::PostgreSQL;
168 4     4   224922 use base 'Module::Build::Database';
  4         31  
  4         1340  
169 4     4   26 use File::Temp qw/tempdir/;
  4         8  
  4         199  
170 4     4   19 use File::Path qw/rmtree/;
  4         6  
  4         132  
171 4     4   20 use File::Basename qw/dirname/;
  4         5  
  4         136  
172 4     4   1731 use File::Copy::Recursive qw/fcopy dirmove/;
  4         11815  
  4         221  
173 4     4   26 use Path::Class qw/file/;
  4         7  
  4         133  
174 4     4   17 use IO::File;
  4         33  
  4         430  
175 4     4   40 use File::Which qw( which );
  4         6  
  4         142  
176              
177 4     4   2440 use Module::Build::Database::PostgreSQL::Templates;
  4         9  
  4         113  
178 4     4   15 use Module::Build::Database::Helpers qw/do_system verify_bin info debug/;
  4         6  
  4         26  
179 4     4   1804 use strict;
  4         8  
  4         72  
180 4     4   12 use warnings;
  4         6  
  4         11654  
181             our $VERSION = '0.58';
182              
183             __PACKAGE__->add_property(database_options => default => { name => "foo", schema => "bar" });
184             __PACKAGE__->add_property(database_extensions => default => { postgis => 0 } );
185             __PACKAGE__->add_property(postgis_base => default => "/usr/local/share/postgis" );
186             __PACKAGE__->add_property(_tmp_db_dir => default => "" );
187             __PACKAGE__->add_property(leave_running => default => 0 ); # leave running after dbtest?
188             __PACKAGE__->add_property(scratch_database => default => { map {; "PG$_" => $ENV{"MBD_SCRATCH_PG$_"} }
189             grep { defined $ENV{"MBD_SCRATCH_PG$_"} }
190             qw( HOST PORT USER ) } );
191              
192             # Binaries used by this module. They should be in $ENV{PATH}.
193             our %Bin = (
194             Psql => 'psql',
195             Pgctl => 'pg_ctl',
196             Postgres => 'postgres',
197             Initdb => 'initdb',
198             Createdb => 'createdb',
199             Dropdb => 'dropdb',
200             Pgdump => 'pg_dump',
201             Pgdoc => [ qw/pg_autodoc postgresql_autodoc/ ],
202             );
203             my $server_bin_dir;
204             if(my $pg_config = which 'pg_config')
205             {
206             $pg_config = Win32::GetShortPathName($pg_config) if $^O eq 'MSWin32' && $pg_config =~ /\s/;
207             $server_bin_dir = `$pg_config --bindir`;
208             chomp $server_bin_dir;
209             $server_bin_dir = Win32::GetShortPathName($server_bin_dir) if $^O eq 'MSWin32' && $server_bin_dir =~ /\s/;
210             undef $server_bin_dir unless -d $server_bin_dir;
211             }
212             verify_bin(\%Bin, $server_bin_dir);
213              
214             sub _do_psql {
215 0     0     my $self = shift;
216 0           my $sql = shift;
217 0           my $database_name = $self->database_options('name');
218 0           my $tmp = File::Temp->new(TEMPLATE => "tmp_db_XXXX", SUFFIX => '.sql');
219 0           print $tmp $sql;
220 0           $tmp->close;
221             # -q: quiet, ON_ERROR_STOP: throw exceptions
222 0           local $ENV{PERL5LIB};
223 0           my $ret = do_system( $Bin{Psql}, "-q", "-vON_ERROR_STOP=1", "-f", "$tmp", $database_name );
224 0           $tmp->unlink_on_destroy($ret);
225 0           $ret;
226             }
227             sub _do_psql_out {
228 0     0     my $self = shift;
229 0           my $sql = shift;
230 0           my $database_name = $self->database_options('name');
231             # -F field separator, -x extended output, -A: unaligned
232 0           local $ENV{PERL5LIB};
233 0           do_system( $Bin{Psql}, "-q", "-vON_ERROR_STOP=1", "-A", "-F ' : '", "-x", "-c", qq["$sql"], $database_name );
234             }
235             sub _do_psql_file {
236 0     0     my $self = shift;
237 0           my $filename = shift;
238 0 0         unless (-e $filename) {
239 0           warn "could not open file $filename";
240 0           return 0;
241             }
242 0 0         unless (-s $filename) {
243 0           warn "file $filename is empty";
244 0           return 0;
245             }
246 0           my $database_name = $self->database_options('name');
247             # -q: quiet, ON_ERROR_STOP: throw exceptions
248 0           local $ENV{PERL5LIB};
249 0           do_system($Bin{Psql},"-q","-vON_ERROR_STOP=1","-f",$filename, $database_name);
250             }
251             sub _do_psql_into_file {
252 0     0     my $self = shift;
253 0           my $filename = shift;
254 0           my $sql = shift;
255 0           my $database_name = $self->database_options('name');
256             # -A: unaligned, -F: field separator, -t: tuples only, ON_ERROR_STOP: throw exceptions
257 0           local $ENV{PERL5LIB};
258 0 0         my $q = $^O eq 'MSWin32' ? '"' : "'";
259 0           do_system( $Bin{Psql}, "-q", "-vON_ERROR_STOP=1", "-A", "-F $q\t$q", "-t", "-c", qq["$sql"], $database_name, ">", "$filename" );
260             }
261             sub _do_psql_capture {
262 0     0     my $self = shift;
263 0           my $sql = shift;
264 0           my $database_name = $self->database_options('name');
265 0           local $ENV{PERL5LIB};
266 0           return qx[$Bin{Psql} -c "$sql" $database_name];
267             }
268              
269             sub _cleanup_old_dbs {
270 0     0     my $self = shift;
271 0           my %args = @_; # pass all => 1 to clean up the current one too
272              
273 0           my $glob;
274             {
275 0           my $tmpdir = tempdir("mbdtest_XXXXXX", TMPDIR => 1);
  0            
276 0           $glob = "$tmpdir";
277 0           rmtree($tmpdir);
278             }
279 0           $glob =~ s/mbdtest_.*$/mbdtest_*/;
280 0           for my $thisdir (glob $glob) {
281 0 0 0       next unless -d $thisdir && -w $thisdir;
282 0           debug "cleaning up old tmp instance : $thisdir";
283 0           $self->_stop_db("$thisdir/db");
284 0           rmtree($thisdir);
285             }
286             }
287              
288             sub _start_new_db {
289 0     0     my $self = shift;
290             # Start a new database and return the host on which it was started.
291              
292 0           my $database_name = $self->database_options('name');
293 0           $ENV{PGDATABASE} = $database_name;
294              
295 0 0         if(%{ $self->scratch_database }) {
  0            
296 0           delete @ENV{qw( PGHOST PGUSER PGPORT )};
297 0           %ENV = (%ENV, %{ $self->scratch_database });
  0            
298 0           do_system("_silent", $Bin{Dropdb}, $database_name);
299              
300             } else {
301              
302 0           $self->_cleanup_old_dbs();
303              
304 0           my $tmpdir = tempdir("mbdtest_XXXXXX", TMPDIR => 1);
305 0           my $dbdir = $tmpdir."/db";
306 0           my $initlog = "$tmpdir/postgres.log";
307 0           $self->_tmp_db_dir($dbdir);
308              
309 0           $ENV{PGHOST} = "$dbdir"; # makes psql use a socket, not a tcp port
310 0           delete $ENV{PGUSER};
311 0           delete $ENV{PGPORT};
312              
313 0           debug "initializing database (log: $initlog)";
314              
315 0 0         do_system($Bin{Initdb}, "-D", "$dbdir", ">>", "$initlog", "2>&1") or do {
316 0           my $log = '';
317 0 0         $log = file($initlog)->slurp if -e $initlog;
318 0           die "could not initdb ($Bin{Initdb})\n$log\n";
319             };
320              
321 0 0         if (my $conf_append = $self->database_options('append_to_conf')) {
322 0 0         die "cannot find postgresql.conf" unless -e "$dbdir/postgresql.conf";
323 0 0         open my $fp, ">> $dbdir/postgresql.conf" or die "could not open postgresql.conf : $!";
324 0           print $fp $conf_append;
325 0           close $fp;
326             }
327              
328 0           my $pmopts = qq[-k $dbdir -h '' -p 5432];
329              
330 0           debug "# starting postgres in $dbdir";
331 0 0         do_system($Bin{Pgctl}, qq[-o "$pmopts"], "-w", "-t", 120, "-D", "$dbdir", "-l", "postmaster.log", "start") or do {
332 0           my $log;
333 0 0         if (-e "$dbdir/postmaster.log") {
334 0           $log = file("$dbdir/postmaster.log")->slurp;
335             } else {
336 0           $log = "no log file : $dbdir/postmaster.log";
337             }
338 0           die "could not start postgres\n$log\n ";
339             };
340              
341 0           my $domain = $dbdir.'/.s.PGSQL.5432';
342 0 0         -e $domain or die "could not find $domain";
343             }
344              
345 0           $self->_create_database();
346              
347 0           return $self->_dbhost;
348             }
349              
350             sub _remove_db {
351 0     0     my $self = shift;
352 0 0 0       return if $ENV{MBD_DONT_STOP_TEST_DB} || %{ $self->scratch_database };
  0            
353 0   0       my $dbdir = shift || $self->_tmp_db_dir();
354 0           $dbdir =~ s/\/db$//;
355 0           rmtree $dbdir;
356             }
357              
358             sub _stop_db {
359 0     0     my $self = shift;
360 0 0 0       return if $ENV{MBD_DONT_STOP_TEST_DB} || %{ $self->scratch_database };
  0            
361 0   0       my $dbdir = shift || $self->_tmp_db_dir();
362 0           my $pid_file = "$dbdir/postmaster.pid";
363 0 0         unless (-e $pid_file) {
364 0           debug "no pid file ($pid_file), not stopping db";
365 0           return;
366             }
367 0           my ($pid) = IO::File->new("<$pid_file")->getlines;
368 0           chomp $pid;
369 0           kill "TERM", $pid;
370 0           sleep 1;
371 0 0         return unless kill 0, $pid;
372 0 0         kill 9, $pid or info "could not send signal to $pid";
373             }
374              
375             sub _apply_base_sql {
376 0     0     my $self = shift;
377 0   0       my $filename = shift || $self->base_dir."/db/dist/base.sql";
378 0 0         return unless -e $filename;
379 0           info "applying base.sql";
380 0           $self->_do_psql_file($filename);
381             }
382              
383             sub _apply_base_data {
384 0     0     my $self = shift;
385 0   0       my $filename = shift || $self->base_dir."/db/dist/base_data.sql";
386 0 0         return 1 unless -e $filename;
387 0           info "applying base_data.sql";
388 0           $self->_do_psql_file($filename);
389             }
390              
391             sub _dump_base_sql {
392             # Optional parameter "outfile" gives the name of the file into which to dump the schema.
393             # If the parameter is omitted, dump and atomically rename to db/dist/base.sql.
394 0     0     my $self = shift;
395 0           my %args = @_;
396 0   0       my $outfile = $args{outfile} || $self->base_dir. "/db/dist/base.sql";
397              
398 0           my $tmpfile = file( tempdir( CLEANUP => 1 ), 'dump.sql');
399              
400             # -x : no privileges, -O : no owner, -s : schema only, -n : only this schema
401 0           my $database_schema = $self->database_options('schema');
402 0           my $database_name = $self->database_options('name');
403 0           local $ENV{PERL5LIB};
404             do_system( $Bin{Pgdump}, "-xOs", "-E", "utf8", "-n", $database_schema, $database_name, ">", $tmpfile )
405 0 0         or do {
406 0           info "Error running pgdump";
407 0           die "Error running pgdump : $! ${^CHILD_ERROR_NATIVE}";
408 0           return 0;
409             };
410              
411 0           my @lines = $tmpfile->slurp();
412 0 0         unless (@lines) {
413 0           die "# Could not run pgdump and write to $tmpfile";
414             }
415             @lines = grep {
416 0   0       $_ !~ /^--/
  0            
417             and $_ !~ /^CREATE SCHEMA $database_schema;$/
418             and $_ !~ /^SET (search_path|lock_timeout)/
419             } @lines;
420 0           file($outfile)->spew(join '', @lines);
421 0 0 0       if (@lines > 0 && !-s $outfile) {
422 0           die "# Unable to write to $outfile";
423             }
424 0           return 1;
425             }
426              
427             sub _dump_base_data {
428             # Optional parameter "outfile, defaults to db/dist/base_data.sql
429 0     0     my $self = shift;
430 0           my %args = @_;
431 0   0       my $outfile = $args{outfile} || $self->base_dir. "/db/dist/base_data.sql";
432              
433 0           my $tmpfile = File::Temp->new(
434             TEMPLATE => (dirname $outfile)."/dump_XXXXXX",
435             UNLINK => 0
436             );
437 0           $tmpfile->close;
438              
439             # -x : no privileges, -O : no owner, -s : schema only, -n : only this schema
440 0           my $database_schema = $self->database_options('schema');
441 0           my $database_name = $self->database_options('name');
442 0           local $ENV{PERL5LIB};
443 0 0         do_system( $Bin{Pgdump}, "--data-only", "-xO", "-E", "utf8", "-n", $database_schema, $database_name,
444             "|", "egrep -v '^SET (lock_timeout|search_path)'",
445             ">", "$tmpfile" )
446             or return 0;
447 0 0         rename "$tmpfile", $outfile or die "rename failed: $!";
448             }
449              
450             sub _apply_patch {
451 0     0     my $self = shift;
452 0           my $patch_file = shift;
453              
454 0           return $self->_do_psql_file($self->base_dir."/db/patches/$patch_file");
455             }
456              
457             sub _is_fresh_install {
458 0     0     my $self = shift;
459              
460 0           my $database_name = $self->database_options('name');
461 0 0         unless ($self->_database_exists) {
462 0           info "database $database_name does not exist";
463 0           return 1;
464             }
465              
466 0           my $file = File::Temp->new(); $file->close;
  0            
467 0           my $database_schema = $self->database_options('schema');
468 0           $self->_do_psql_into_file("$file","\\dn $database_schema");
469 0           return !do_system("_silent","grep -q $database_schema $file");
470             }
471              
472             sub _show_live_db {
473             # Display the connection information
474 0     0     my $self = shift;
475              
476 0   0       info "PGUSER : " . ( $ENV{PGUSER} || "" );
477 0   0       info "PGHOST : " . ( $ENV{PGHOST} || "" );
478 0   0       info "PGPORT : " . ( $ENV{PGPORT} || "" );
479              
480 0   0       my $database_name = shift || $self->database_options('name');
481 0           info "database : $database_name";
482              
483 0 0         return unless $self->_database_exists;
484 0           $self->_do_psql_out("select current_database(),session_user,version();");
485             }
486              
487             sub _patch_table_exists {
488             # returns true or false
489 0     0     my $self = shift;
490 0           my $file = File::Temp->new(); $file->close;
  0            
491 0           my $database_schema = $self->database_options('schema');
492 0           $self->_do_psql_into_file("$file","select tablename from pg_tables where tablename='patches_applied' and schemaname = '$database_schema'");
493 0           return do_system("_silent","grep -q patches_applied $file");
494             }
495              
496             sub _dump_patch_table {
497             # Dump the patch table in an existing db into a flat file, that
498             # will be in the same format as patches_applied.txt.
499 0     0     my $self = shift;
500 0           my %args = @_;
501 0 0         my $filename = $args{outfile} or Carp::confess "need a filename";
502 0           my $database_schema = $self->database_options('schema');
503 0           $self->_do_psql_into_file($filename,"select patch_name,patch_md5 from $database_schema.patches_applied order by patch_name");
504             }
505              
506             sub _create_patch_table {
507 0     0     my $self = shift;
508             # create a new patch table
509 0           my $database_schema = $self->database_options('schema');
510 0           my $sql = <
511             CREATE TABLE $database_schema.patches_applied (
512             patch_name varchar(255) primary key,
513             patch_md5 varchar(255),
514             when_applied timestamp );
515             EOSQL
516 0           $self->_do_psql($sql);
517             }
518              
519             sub _insert_patch_record {
520 0     0     my $self = shift;
521 0           my $record = shift;
522 0           my ($name,$md5) = @$record;
523 0           my $database_schema = $self->database_options('schema');
524 0           $self->_do_psql("insert into $database_schema.patches_applied (patch_name, patch_md5, when_applied) ".
525             " values ('$name','$md5',now()) ");
526             }
527              
528             sub _database_exists {
529 0     0     my $self = shift;
530 0   0       my $database_name = shift || $self->database_options('name');
531 0           local $ENV{PERL5LIB};
532 0           scalar grep /^$database_name$/, map { [split /:/]->[0] } `psql -Alt -F:`;
  0            
533             }
534              
535             sub _create_language_extensions {
536 0     0     my $self = shift;
537 0           my $list = $self->database_extensions('languages');
538 0 0         return unless $list;
539 0           foreach my $lang (@$list) {
540 0 0         $self->_do_psql("create extension if not exists $lang") || die "error creating language: $lang";
541             }
542             }
543              
544             sub _create_database {
545 0     0     my $self = shift;
546              
547 0           my $database_name = $self->database_options('name');
548 0           my $database_schema = $self->database_options('schema');
549              
550             # create the database if necessary
551 0 0         unless ($self->_database_exists($database_name)) {
552 0           local $ENV{PERL5LIB};
553 0 0         do_system($Bin{Createdb}, $database_name) or die "could not createdb";
554             }
555              
556             # Create a fresh schema in the database.
557 0 0         $self->_do_psql("create schema $database_schema") unless $database_schema eq 'public';
558              
559 0           $self->_do_psql("alter database $database_name set client_min_messages to ERROR");
560              
561 0           $self->_do_psql("alter database $database_name set search_path to $database_schema;");
562              
563             # stolen from http://wiki.postgresql.org/wiki/CREATE_OR_REPLACE_LANGUAGE
564 0           $self->_do_psql(<<'SAFE_MAKE_PLPGSQL');
565             CREATE OR REPLACE FUNCTION make_plpgsql()
566             RETURNS VOID
567             LANGUAGE SQL
568             AS $$
569             CREATE LANGUAGE plpgsql;
570             $$;
571              
572             SELECT
573             CASE
574             WHEN EXISTS(
575             SELECT 1
576             FROM pg_catalog.pg_language
577             WHERE lanname='plpgsql'
578             )
579             THEN NULL
580             ELSE make_plpgsql() END;
581              
582             DROP FUNCTION make_plpgsql();
583             SAFE_MAKE_PLPGSQL
584              
585 0 0         if (my $postgis = $self->database_extensions('postgis')) {
586 0           info "applying postgis extension";
587 0 0         my $postgis_schema = $postgis->{schema} or die "No schema given for postgis";
588 0 0         $self->_do_psql("create schema $postgis_schema") unless $postgis_schema eq 'public';
589 0           $self->_do_psql("alter database $database_name set search_path to $postgis_schema;");
590             # We need to run "createlang plpgsql" first.
591 0 0         $self->_do_psql_file($self->postgis_base. "/postgis.sql") or die "could not do postgis.sql";
592 0 0         $self->_do_psql_file($self->postgis_base. "/spatial_ref_sys.sql") or die "could not do spatial_ref_sys.sql";
593 0           $self->_do_psql("alter database $database_name set search_path to $database_schema, $postgis_schema");
594             }
595              
596 0 0         if (my $sql = $self->database_options('post_initdb')) {
597 0           info "applying post_initdb (nb: this option has been renamed to 'after_create')";
598 0           $self->_do_psql($sql);
599             }
600              
601 0 0         if (my $sql = $self->database_options('after_create')) {
602 0           info "applying after_create";
603 0           $self->_do_psql($sql);
604             }
605              
606 0           1;
607             }
608              
609             sub _remove_patches_applied_table {
610 0     0     my $self = shift;
611 0           my $database_schema = $self->database_options('schema');
612 0           $self->_do_psql("drop table if exists $database_schema.patches_applied;");
613             }
614              
615             sub _generate_docs {
616 0     0     my $self = shift;
617 0           my %args = @_;
618 0 0         my $dir = $args{dir} or die "missing dir";
619 0           my $tmpdir = tempdir;
620 0           my $tc = "Module::Build::Database::PostgreSQL::Templates";
621 0           my $database_name = $self->database_options('name');
622 0           my $database_schema = $self->database_options('schema');
623              
624 0           $self->_start_new_db();
625 0           $self->_apply_base_sql();
626              
627 0           chdir $tmpdir;
628 0           for my $filename ($tc->filenames) {
629 0 0         open my $fp, ">$filename" or die $!;
630 0           print ${fp} $tc->file_contents($filename);
631 0           close $fp;
632             }
633              
634             # http://perlmonks.org/?node_id=821413
635 0           do_system( $Bin{Pgdoc}, "-d", $database_name, "-s", $database_schema, "-l .", "-t pod" );
636 0           do_system( $Bin{Pgdoc}, "-d", $database_name, "-s", $database_schema, "-l .", "-t html" );
637 0           do_system( $Bin{Pgdoc}, "-d", $database_name, "-s", $database_schema, "-l .", "-t dot" );
638              
639 0           for my $type (qw(pod html)) {
640 0 0         my $fp = IO::File->new("<$database_name.$type") or die $!;
641 0 0         mkdir $type or die $!;
642 0           my $outfp;
643 0           while (<$fp>) {
644 0 0         s/^_CUT: (.*)$// and do { $outfp = IO::File->new(">$type/$1") or die $!; };
  0 0          
645 0 0         s/^_DB: (.*)$// and do { $_ = $self->_do_psql_capture($1); s/^/ /gm; };
  0            
  0            
646 0 0         print ${outfp} $_ if defined($outfp);
647             }
648             }
649 0           dirmove "$tmpdir/pod", "$dir/pod";
650 0           info "Generated $dir/pod";
651 0           dirmove "$tmpdir/html", "$dir/html";
652 0           info "Generated $dir/html";
653 0           fcopy "$tmpdir/$database_name.dot", "$dir";
654 0           info "Generated $dir/$database_name.dot";
655             }
656              
657 0     0 0   sub ACTION_dbtest { shift->SUPER::ACTION_dbtest(@_); }
658 0     0 0   sub ACTION_dbclean { shift->SUPER::ACTION_dbclean(@_); }
659 0     0 0   sub ACTION_dbdist { shift->SUPER::ACTION_dbdist(@_); }
660 0     0 0   sub ACTION_dbdocs { shift->SUPER::ACTION_dbdocs(@_); }
661 0     0 0   sub ACTION_dbinstall { shift->SUPER::ACTION_dbinstall(@_); }
662 0     0 0   sub ACTION_dbfakeinstall { shift->SUPER::ACTION_dbfakeinstall(@_); }
663              
664             sub _dbhost {
665 0   0 0     return $ENV{PGHOST} || 'localhost';
666             }
667              
668             1;
669