1package App::Info::RDBMS::PostgreSQL; 2 3=head1 NAME 4 5App::Info::RDBMS::PostgreSQL - Information about PostgreSQL 6 7=head1 SYNOPSIS 8 9 use App::Info::RDBMS::PostgreSQL; 10 11 my $pg = App::Info::RDBMS::PostgreSQL->new; 12 13 if ($pg->installed) { 14 print "App name: ", $pg->name, "\n"; 15 print "Version: ", $pg->version, "\n"; 16 print "Bin dir: ", $pg->bin_dir, "\n"; 17 } else { 18 print "PostgreSQL is not installed. :-(\n"; 19 } 20 21=head1 DESCRIPTION 22 23App::Info::RDBMS::PostgreSQL supplies information about the PostgreSQL 24database server installed on the local system. It implements all of the 25methods defined by App::Info::RDBMS. Methods that trigger events will trigger 26them only the first time they're called (See L<App::Info|App::Info> for 27documentation on handling events). To start over (after, say, someone has 28installed PostgreSQL) construct a new App::Info::RDBMS::PostgreSQL object to 29aggregate new meta data. 30 31Some of the methods trigger the same events. This is due to cross-calling of 32shared subroutines. However, any one event should be triggered no more than 33once. For example, although the info event "Executing `pg_config --version`" 34is documented for the methods C<name()>, C<version()>, C<major_version()>, 35C<minor_version()>, and C<patch_version()>, rest assured that it will only be 36triggered once, by whichever of those four methods is called first. 37 38=cut 39 40use strict; 41use App::Info::RDBMS; 42use App::Info::Util; 43use vars qw(@ISA $VERSION); 44@ISA = qw(App::Info::RDBMS); 45$VERSION = '0.57'; 46use constant WIN32 => $^O eq 'MSWin32'; 47 48my $u = App::Info::Util->new; 49my @EXES = qw(postgres createdb createlang createuser dropdb droplang 50 dropuser initdb pg_dump pg_dumpall pg_restore postmaster 51 vacuumdb psql); 52 53=head1 INTERFACE 54 55=head2 Constructor 56 57=head3 new 58 59 my $pg = App::Info::RDBMS::PostgreSQL->new(@params); 60 61Returns an App::Info::RDBMS::PostgreSQL object. See L<App::Info|App::Info> for 62a complete description of argument parameters. 63 64When it called, C<new()> searches the file system for an executable named for 65the list returned by C<search_exe_names()>, usually F<pg_config>, in the list 66of directories returned by C<search_bin_dirs()>. If found, F<pg_config> will 67be called by the object methods below to gather the data necessary for 68each. If F<pg_config> cannot be found, then PostgreSQL is assumed not to be 69installed, and each of the object methods will return C<undef>. 70 71C<new()> also takes a number of optional parameters in addition to those 72documented for App::Info. These parameters allow you to specify alternate 73names for PostgreSQL executables (other than F<pg_config>, which you specify 74via the C<search_exe_names> parameter). These parameters are: 75 76=over 77 78=item search_postgres_names 79 80=item search_createdb_names 81 82=item search_createlang_names 83 84=item search_createuser_names 85 86=item search_dropd_names 87 88=item search_droplang_names 89 90=item search_dropuser_names 91 92=item search_initdb_names 93 94=item search_pg_dump_names 95 96=item search_pg_dumpall_names 97 98=item search_pg_restore_names 99 100=item search_postmaster_names 101 102=item search_psql_names 103 104=item search_vacuumdb_names 105 106=back 107 108B<Events:> 109 110=over 4 111 112=item info 113 114Looking for pg_config 115 116=item confirm 117 118Path to pg_config? 119 120=item unknown 121 122Path to pg_config? 123 124=back 125 126=cut 127 128sub new { 129 # Construct the object. 130 my $self = shift->SUPER::new(@_); 131 132 # Find pg_config. 133 $self->info("Looking for pg_config"); 134 135 my @paths = $self->search_bin_dirs; 136 my @exes = $self->search_exe_names; 137 138 if (my $cfg = $u->first_cat_exe(\@exes, @paths)) { 139 # We found it. Confirm. 140 $self->{pg_config} = $self->confirm( key => 'path to pg_config', 141 prompt => "Path to pg_config?", 142 value => $cfg, 143 callback => sub { -x }, 144 error => 'Not an executable'); 145 } else { 146 # Handle an unknown value. 147 $self->{pg_config} = $self->unknown( key => 'path to pg_config', 148 prompt => "Path to pg_config?", 149 callback => sub { -x }, 150 error => 'Not an executable'); 151 } 152 153 # Set up search defaults. 154 for my $exe (@EXES) { 155 my $attr = "search_$exe\_names"; 156 if (exists $self->{$attr}) { 157 $self->{$attr} = [$self->{$attr}] unless ref $self->{$attr} eq 'ARRAY'; 158 } else { 159 $self->{$attr} = []; 160 } 161 } 162 163 return $self; 164} 165 166# We'll use this code reference as a common way of collecting data. 167my $get_data = sub { 168 return unless $_[0]->{pg_config}; 169 $_[0]->info(qq{Executing `"$_[0]->{pg_config}" $_[1]`}); 170 my $info = `"$_[0]->{pg_config}" $_[1]`; 171 chomp $info; 172 return $info; 173}; 174 175############################################################################## 176 177=head2 Class Method 178 179=head3 key_name 180 181 my $key_name = App::Info::RDBMS::PostgreSQL->key_name; 182 183Returns the unique key name that describes this class. The value returned is 184the string "PostgreSQL". 185 186=cut 187 188sub key_name { 'PostgreSQL' } 189 190############################################################################## 191 192=head2 Object Methods 193 194=head3 installed 195 196 print "PostgreSQL is ", ($pg->installed ? '' : 'not '), "installed.\n"; 197 198Returns true if PostgreSQL is installed, and false if it is not. 199App::Info::RDBMS::PostgreSQL determines whether PostgreSQL is installed based 200on the presence or absence of the F<pg_config> application on the file system 201as found when C<new()> constructed the object. If PostgreSQL does not appear 202to be installed, then all of the other object methods will return empty 203values. 204 205=cut 206 207sub installed { return $_[0]->{pg_config} ? 1 : undef } 208 209############################################################################## 210 211=head3 name 212 213 my $name = $pg->name; 214 215Returns the name of the application. App::Info::RDBMS::PostgreSQL parses the 216name from the system call C<`pg_config --version`>. 217 218B<Events:> 219 220=over 4 221 222=item info 223 224Executing `pg_config --version` 225 226=item error 227 228Failed to find PostgreSQL version with `pg_config --version` 229 230Unable to parse name from string 231 232Unable to parse version from string 233 234Failed to parse PostgreSQL version parts from string 235 236=item unknown 237 238Enter a valid PostgreSQL name 239 240=back 241 242=cut 243 244# This code reference is used by name(), version(), major_version(), 245# minor_version(), and patch_version() to aggregate the data they need. 246my $get_version = sub { 247 my $self = shift; 248 $self->{'--version'} = 1; 249 my $data = $get_data->($self, '--version'); 250 unless ($data) { 251 $self->error("Failed to find PostgreSQL version with ". 252 "`$self->{pg_config} --version`"); 253 return; 254 } 255 256 chomp $data; 257 my ($name, $version) = split /\s+/, $data, 2; 258 259 # Check for and assign the name. 260 $name ? 261 $self->{name} = $name : 262 $self->error("Unable to parse name from string '$data'"); 263 264 # Parse the version number. 265 if ($version) { 266 my ($x, $y, $z) = $version =~ /(\d+)\.(\d+).(\d+)/; 267 if (defined $x and defined $y and defined $z) { 268 # Beta/devel/release candidates are treated as patch level "0" 269 @{$self}{qw(version major minor patch)} = 270 ($version, $x, $y, $z); 271 } elsif ($version =~ /(\d+)\.(\d+)/) { 272 # New versions, such as "7.4", are treated as patch level "0" 273 @{$self}{qw(version major minor patch)} = 274 ($version, $1, $2, 0); 275 } else { 276 $self->error("Failed to parse PostgreSQL version parts from " . 277 "string '$version'"); 278 } 279 } else { 280 $self->error("Unable to parse version from string '$data'"); 281 } 282}; 283 284sub name { 285 my $self = shift; 286 return unless $self->{pg_config}; 287 288 # Load data. 289 $get_version->($self) unless $self->{'--version'}; 290 291 # Handle an unknown name. 292 $self->{name} ||= $self->unknown( key => 'postgres name' ); 293 294 # Return the name. 295 return $self->{name}; 296} 297 298############################################################################## 299 300=head3 version 301 302 my $version = $pg->version; 303 304Returns the PostgreSQL version number. App::Info::RDBMS::PostgreSQL parses the 305version number from the system call C<`pg_config --version`>. 306 307B<Events:> 308 309=over 4 310 311=item info 312 313Executing `pg_config --version` 314 315=item error 316 317Failed to find PostgreSQL version with `pg_config --version` 318 319Unable to parse name from string 320 321Unable to parse version from string 322 323Failed to parse PostgreSQL version parts from string 324 325=item unknown 326 327Enter a valid PostgreSQL version number 328 329=back 330 331=cut 332 333sub version { 334 my $self = shift; 335 return unless $self->{pg_config}; 336 337 # Load data. 338 $get_version->($self) unless $self->{'--version'}; 339 340 # Handle an unknown value. 341 unless ($self->{version}) { 342 # Create a validation code reference. 343 my $chk_version = sub { 344 # Try to get the version number parts. 345 my ($x, $y, $z) = /^(\d+)\.(\d+).(\d+)$/; 346 # Return false if we didn't get all three. 347 return unless $x and defined $y and defined $z; 348 # Save all three parts. 349 @{$self}{qw(major minor patch)} = ($x, $y, $z); 350 # Return true. 351 return 1; 352 }; 353 $self->{version} = $self->unknown( key => 'postgres version number', 354 callback => $chk_version); 355 } 356 357 return $self->{version}; 358} 359 360############################################################################## 361 362=head3 major version 363 364 my $major_version = $pg->major_version; 365 366Returns the PostgreSQL major version number. App::Info::RDBMS::PostgreSQL 367parses the major version number from the system call C<`pg_config --version`>. 368For example, if C<version()> returns "7.1.2", then this method returns "7". 369 370B<Events:> 371 372=over 4 373 374=item info 375 376Executing `pg_config --version` 377 378=item error 379 380Failed to find PostgreSQL version with `pg_config --version` 381 382Unable to parse name from string 383 384Unable to parse version from string 385 386Failed to parse PostgreSQL version parts from string 387 388=item unknown 389 390Enter a valid PostgreSQL major version number 391 392=back 393 394=cut 395 396# This code reference is used by major_version(), minor_version(), and 397# patch_version() to validate a version number entered by a user. 398my $is_int = sub { /^\d+$/ }; 399 400sub major_version { 401 my $self = shift; 402 return unless $self->{pg_config}; 403 # Load data. 404 $get_version->($self) unless exists $self->{'--version'}; 405 # Handle an unknown value. 406 $self->{major} = $self->unknown( key => 'postgres major version number', 407 callback => $is_int) 408 unless $self->{major}; 409 return $self->{major}; 410} 411 412############################################################################## 413 414=head3 minor version 415 416 my $minor_version = $pg->minor_version; 417 418Returns the PostgreSQL minor version number. App::Info::RDBMS::PostgreSQL 419parses the minor version number from the system call C<`pg_config --version`>. 420For example, if C<version()> returns "7.1.2", then this method returns "2". 421 422B<Events:> 423 424=over 4 425 426=item info 427 428Executing `pg_config --version` 429 430=item error 431 432Failed to find PostgreSQL version with `pg_config --version` 433 434Unable to parse name from string 435 436Unable to parse version from string 437 438Failed to parse PostgreSQL version parts from string 439 440=item unknown 441 442Enter a valid PostgreSQL minor version number 443 444=back 445 446=cut 447 448sub minor_version { 449 my $self = shift; 450 return unless $self->{pg_config}; 451 # Load data. 452 $get_version->($self) unless exists $self->{'--version'}; 453 # Handle an unknown value. 454 $self->{minor} = $self->unknown( key => 'postgres minor version number', 455 callback => $is_int) 456 unless defined $self->{minor}; 457 return $self->{minor}; 458} 459 460############################################################################## 461 462=head3 patch version 463 464 my $patch_version = $pg->patch_version; 465 466Returns the PostgreSQL patch version number. App::Info::RDBMS::PostgreSQL 467parses the patch version number from the system call C<`pg_config --version`>. 468For example, if C<version()> returns "7.1.2", then this method returns "1". 469 470B<Events:> 471 472=over 4 473 474=item info 475 476Executing `pg_config --version` 477 478=item error 479 480Failed to find PostgreSQL version with `pg_config --version` 481 482Unable to parse name from string 483 484Unable to parse version from string 485 486Failed to parse PostgreSQL version parts from string 487 488=item unknown 489 490Enter a valid PostgreSQL minor version number 491 492=back 493 494=cut 495 496sub patch_version { 497 my $self = shift; 498 return unless $self->{pg_config}; 499 # Load data. 500 $get_version->($self) unless exists $self->{'--version'}; 501 # Handle an unknown value. 502 $self->{patch} = $self->unknown( key => 'postgres patch version number', 503 callback => $is_int) 504 unless defined $self->{patch}; 505 return $self->{patch}; 506} 507 508############################################################################## 509 510=head3 executable 511 512 my $exe = $pg->executable; 513 514Returns the full path to the PostgreSQL server executable, which is named 515F<postgres>. This method does not use the executable names returned by 516C<search_exe_names()>; those executable names are used to search for 517F<pg_config> only (in C<new()>). 518 519When it called, C<executable()> checks for an executable named F<postgres> in 520the directory returned by C<bin_dir()>. 521 522Note that C<executable()> is simply an alias for C<postgres()>. 523 524B<Events:> 525 526=over 4 527 528=item info 529 530Looking for postgres executable 531 532=item confirm 533 534Path to postgres executable? 535 536=item unknown 537 538Path to postgres executable? 539 540=back 541 542=cut 543 544my $find_exe = sub { 545 my ($self, $key) = @_; 546 my $exe = $key . (WIN32 ? '.exe' : ''); 547 my $meth = "search_$key\_names"; 548 549 # Find executable. 550 $self->info("Looking for $key"); 551 552 unless ($self->{$key}) { 553 my $bin = $self->bin_dir or return; 554 if (my $exe = $u->first_cat_exe([$self->$meth(), $exe], $bin)) { 555 # We found it. Confirm. 556 $self->{$key} = $self->confirm( 557 key => "path to $key", 558 prompt => "Path to $key executable?", 559 value => $exe, 560 callback => sub { -x }, 561 error => 'Not an executable' 562 ); 563 } else { 564 # Handle an unknown value. 565 $self->{$key} = $self->unknown( 566 key => "path to $key", 567 prompt => "Path to $key executable?", 568 callback => sub { -x }, 569 error => 'Not an executable' 570 ); 571 } 572 } 573 574 return $self->{$key}; 575}; 576 577for my $exe (@EXES) { 578 no strict 'refs'; 579 *{$exe} = sub { shift->$find_exe($exe) }; 580 *{"search_$exe\_names"} = sub { @{ shift->{"search_$exe\_names"} } } 581} 582 583*executable = \&postgres; 584 585############################################################################## 586 587=head3 bin_dir 588 589 my $bin_dir = $pg->bin_dir; 590 591Returns the PostgreSQL binary directory path. App::Info::RDBMS::PostgreSQL 592gathers the path from the system call C<`pg_config --bindir`>. 593 594B<Events:> 595 596=over 4 597 598=item info 599 600Executing `pg_config --bindir` 601 602=item error 603 604Cannot find bin directory 605 606=item unknown 607 608Enter a valid PostgreSQL bin directory 609 610=back 611 612=cut 613 614# This code reference is used by bin_dir(), lib_dir(), and so_lib_dir() to 615# validate a directory entered by the user. 616my $is_dir = sub { -d }; 617 618sub bin_dir { 619 my $self = shift; 620 return unless $self->{pg_config}; 621 unless (exists $self->{bin_dir} ) { 622 if (my $dir = $get_data->($self, '--bindir')) { 623 $self->{bin_dir} = $dir; 624 } else { 625 # Handle an unknown value. 626 $self->error("Cannot find bin directory"); 627 $self->{bin_dir} = $self->unknown( key => 'postgres bin dir', 628 callback => $is_dir) 629 } 630 } 631 632 return $self->{bin_dir}; 633} 634 635############################################################################## 636 637=head3 inc_dir 638 639 my $inc_dir = $pg->inc_dir; 640 641Returns the PostgreSQL include directory path. App::Info::RDBMS::PostgreSQL 642gathers the path from the system call C<`pg_config --includedir`>. 643 644B<Events:> 645 646=over 4 647 648=item info 649 650Executing `pg_config --includedir` 651 652=item error 653 654Cannot find include directory 655 656=item unknown 657 658Enter a valid PostgreSQL include directory 659 660=back 661 662=cut 663 664sub inc_dir { 665 my $self = shift; 666 return unless $self->{pg_config}; 667 unless (exists $self->{inc_dir} ) { 668 if (my $dir = $get_data->($self, '--includedir')) { 669 $self->{inc_dir} = $dir; 670 } else { 671 # Handle an unknown value. 672 $self->error("Cannot find include directory"); 673 $self->{inc_dir} = $self->unknown( key => 'postgres include dir', 674 callback => $is_dir) 675 } 676 } 677 678 return $self->{inc_dir}; 679} 680 681############################################################################## 682 683=head3 lib_dir 684 685 my $lib_dir = $pg->lib_dir; 686 687Returns the PostgreSQL library directory path. App::Info::RDBMS::PostgreSQL 688gathers the path from the system call C<`pg_config --libdir`>. 689 690B<Events:> 691 692=over 4 693 694=item info 695 696Executing `pg_config --libdir` 697 698=item error 699 700Cannot find library directory 701 702=item unknown 703 704Enter a valid PostgreSQL library directory 705 706=back 707 708=cut 709 710sub lib_dir { 711 my $self = shift; 712 return unless $self->{pg_config}; 713 unless (exists $self->{lib_dir} ) { 714 if (my $dir = $get_data->($self, '--libdir')) { 715 $self->{lib_dir} = $dir; 716 } else { 717 # Handle an unknown value. 718 $self->error("Cannot find library directory"); 719 $self->{lib_dir} = $self->unknown( key => 'postgres library dir', 720 callback => $is_dir) 721 } 722 } 723 724 return $self->{lib_dir}; 725} 726 727############################################################################## 728 729=head3 so_lib_dir 730 731 my $so_lib_dir = $pg->so_lib_dir; 732 733Returns the PostgreSQL shared object library directory path. 734App::Info::RDBMS::PostgreSQL gathers the path from the system call 735C<`pg_config --pkglibdir`>. 736 737B<Events:> 738 739=over 4 740 741=item info 742 743Executing `pg_config --pkglibdir` 744 745=item error 746 747Cannot find shared object library directory 748 749=item unknown 750 751Enter a valid PostgreSQL shared object library directory 752 753=back 754 755=cut 756 757# Location of dynamically loadable modules. 758sub so_lib_dir { 759 my $self = shift; 760 return unless $self->{pg_config}; 761 unless (exists $self->{so_lib_dir} ) { 762 if (my $dir = $get_data->($self, '--pkglibdir')) { 763 $self->{so_lib_dir} = $dir; 764 } else { 765 # Handle an unknown value. 766 $self->error("Cannot find shared object library directory"); 767 $self->{so_lib_dir} = 768 $self->unknown( key => 'postgres so directory', 769 callback => $is_dir) 770 } 771 } 772 773 return $self->{so_lib_dir}; 774} 775 776############################################################################## 777 778=head3 configure options 779 780 my $configure = $pg->configure; 781 782Returns the options with which the PostgreSQL server was 783configured. App::Info::RDBMS::PostgreSQL gathers the configure data from the 784system call C<`pg_config --configure`>. 785 786B<Events:> 787 788=over 4 789 790=item info 791 792Executing `pg_config --configure` 793 794=item error 795 796Cannot find configure information 797 798=item unknown 799 800Enter PostgreSQL configuration options 801 802=back 803 804=cut 805 806sub configure { 807 my $self = shift; 808 return unless $self->{pg_config}; 809 unless (exists $self->{configure} ) { 810 if (my $conf = $get_data->($self, '--configure')) { 811 $self->{configure} = $conf; 812 } else { 813 # Configure can be empty, so just make sure it exists and is 814 # defined. Don't prompt. 815 $self->{configure} = ''; 816 } 817 } 818 819 return $self->{configure}; 820} 821 822############################################################################## 823 824=head3 home_url 825 826 my $home_url = $pg->home_url; 827 828Returns the PostgreSQL home page URL. 829 830=cut 831 832sub home_url { "http://www.postgresql.org/" } 833 834############################################################################## 835 836=head3 download_url 837 838 my $download_url = $pg->download_url; 839 840Returns the PostgreSQL download URL. 841 842=cut 843 844sub download_url { "http://www.postgresql.org/mirrors-ftp.html" } 845 846############################################################################## 847 848=head3 search_exe_names 849 850 my @search_exe_names = $app->search_exe_names; 851 852Returns a list of possible names for F<pg_config> executable. By default, only 853F<pg_config> is returned (or F<pg_config.exe> on Win32). 854 855Note that this method is not used to search for the PostgreSQL server 856executable, only F<pg_config>. 857 858=cut 859 860sub search_exe_names { 861 my $self = shift; 862 my $exe = 'pg_config'; 863 $exe .= '.exe' if WIN32; 864 return ($self->SUPER::search_exe_names, $exe); 865} 866 867############################################################################## 868 869=head3 search_bin_dirs 870 871 my @search_bin_dirs = $app->search_bin_dirs; 872 873Returns a list of possible directories in which to search an executable. Used 874by the C<new()> constructor to find an executable to execute and collect 875application info. The found directory will also be returned by the C<bin_dir> 876method. 877 878The list of directories by default consists of the path as defined by 879C<< File::Spec->path >>, as well as the following directories: 880 881=over 4 882 883=item $ENV{POSTGRES_HOME}/bin (if $ENV{POSTGRES_HOME} exists) 884 885=item $ENV{POSTGRES_LIB}/../bin (if $ENV{POSTGRES_LIB} exists) 886 887=item /usr/local/pgsql/bin 888 889=item /usr/local/postgres/bin 890 891=item /opt/pgsql/bin 892 893=item /usr/local/bin 894 895=item /usr/local/sbin 896 897=item /usr/bin 898 899=item /usr/sbin 900 901=item /bin 902 903=item C:\Program Files\PostgreSQL\bin 904 905=back 906 907=cut 908 909sub search_bin_dirs { 910 return shift->SUPER::search_bin_dirs, 911 ( exists $ENV{POSTGRES_HOME} 912 ? ($u->catdir($ENV{POSTGRES_HOME}, "bin")) 913 : () 914 ), 915 ( exists $ENV{POSTGRES_LIB} 916 ? ($u->catdir($ENV{POSTGRES_LIB}, $u->updir, "bin")) 917 : () 918 ), 919 $u->path, 920 qw(/usr/local/pgsql/bin 921 /usr/local/postgres/bin 922 /usr/lib/postgresql/bin 923 /opt/pgsql/bin 924 /usr/local/bin 925 /usr/local/sbin 926 /usr/bin 927 /usr/sbin 928 /bin), 929 'C:\Program Files\PostgreSQL\bin'; 930} 931 932############################################################################## 933 934=head2 Other Executable Methods 935 936These methods function just like the C<executable()> method, except that they 937return different executables. PostgreSQL comes with a fair number of them; we 938provide these methods to provide a path to a subset of them. Each method, when 939called, checks for an executable in the directory returned by C<bin_dir()>. 940The name of the executable must be one of the names returned by the 941corresponding C<search_*_names> method. 942 943The available executable methods are: 944 945=over 946 947=item postgres 948 949=item createdb 950 951=item createlang 952 953=item createuser 954 955=item dropdb 956 957=item droplang 958 959=item dropuser 960 961=item initdb 962 963=item pg_dump 964 965=item pg_dumpall 966 967=item pg_restore 968 969=item postmaster 970 971=item psql 972 973=item vacuumdb 974 975=back 976 977And the corresponding search names methods are: 978 979=over 980 981=item search_postgres_names 982 983=item search_createdb_names 984 985=item search_createlang_names 986 987=item search_createuser_names 988 989=item search_dropd_names 990 991=item search_droplang_names 992 993=item search_dropuser_names 994 995=item search_initdb_names 996 997=item search_pg_dump_names 998 999=item search_pg_dumpall_names 1000 1001=item search_pg_restore_names 1002 1003=item search_postmaster_names 1004 1005=item search_psql_names 1006 1007=item search_vacuumdb_names 1008 1009=back 1010 1011B<Events:> 1012 1013=over 4 1014 1015=item info 1016 1017Looking for executable 1018 1019=item confirm 1020 1021Path to executable? 1022 1023=item unknown 1024 1025Path to executable? 1026 1027=back 1028 1029=cut 1030 10311; 1032__END__ 1033 1034=head1 SUPPORT 1035 1036This module is stored in an open L<GitHub 1037repository|http://github.com/theory/app-info/>. Feel free to fork and 1038contribute! 1039 1040Please file bug reports via L<GitHub 1041Issues|http://github.com/theory/app-info/issues/> or by sending mail to 1042L<bug-App-Info@rt.cpan.org|mailto:bug-App-Info@rt.cpan.org>. 1043 1044=head1 AUTHOR 1045 1046David E. Wheeler <david@justatheory.com> based on code by Sam Tregar 1047<sam@tregar.com>. 1048 1049=head1 SEE ALSO 1050 1051L<App::Info|App::Info> documents the event handling interface. 1052 1053L<App::Info::RDBMS|App::Info::RDBMS> is the App::Info::RDBMS::PostgreSQL 1054parent class. 1055 1056L<DBD::Pg|DBD::Pg> is the L<DBI|DBI> driver for connecting to PostgreSQL 1057databases. 1058 1059L<http://www.postgresql.org/> is the PostgreSQL home page. 1060 1061=head1 COPYRIGHT AND LICENSE 1062 1063Copyright (c) 2002-2011, David E. Wheeler. Some Rights Reserved. 1064 1065This module is free software; you can redistribute it and/or modify it under the 1066same terms as Perl itself. 1067 1068=cut 1069