#!/usr/bin/perl
#
# -----------------------------------------------------------------------------
#  db_exec - Database interface script
# -----------------------------------------------------------------------------
#  Author: Alexey Tsibulnik
#  QA by:  
#  Copyright: videoNEXT LLC
# -----------------------------------------------------------------------------
# usage:         db_exec [OPTIONS] dbname
# options:
#                -f file
#                   Use  the file filename as the source of commands instead of reading commands interactively.
#                -c command
#                   Specifies that db_exec is to execute one command string, command, and then exit.
#                -L filename
#                   Write all query output into file filename, in addition to the normal output  destination
#
# example:       db_exec -L ./select.log -c "select * from _objs" skm_master
# note:          all options which aren't processed by db_exec will be passed directly to DB driver binary
#
use strict;

# CONS
my $APL = $ENV{APL};
my $DB_CONF_PATH = "$APL/etc";

# VAR
my %dbconf; # DB configuration
my %opts;
my @args;

# List of supported DB client apps
my %DRIVERS = (
    PGSQL => {
	run => $^O=~/darwin/i ? "$APL/imp/bin/psql" : '/usr/bin/psql',
	opt => {
	    host     => '-h',
	    dbname   => '-d',
	    username => '-U',
	    logfile  => '-L',
	    file     => '-f',
	    command  => '-c'
	}
    }
);

# MAIN
#
# read conf files
while(<$DB_CONF_PATH/*.db.conf>) {
    my ($dbname) = m|$DB_CONF_PATH/(.+)\.db\.conf$|;
    next unless open CONF, $_;
    my %cfg = map{/(^.+?)=(.*)/} grep {/^.+=.*/} <CONF>;
    close CONF;
    $dbconf{$dbname} = \%cfg;	
}
# parse command line
# try to guess DB name
my $dbname = pop @ARGV;
unless (defined $dbname) {
	die "parameter dbname is missing";
}
elsif(not grep {/^$dbname$/} keys %dbconf) {
	if (@ARGV and $ARGV[$#ARGV]!~/^-/) {
		die "database \"$dbname\" not found\n";
	}
	else {
		die "parameter dbname is missing";
	}
}
# Extract pre-defined arguments
while (my $arg = shift @ARGV) {
    for ($arg) {
	/^-c$/ and do {
	    $opts{command} = shift @ARGV; last;
	};
	/^-f$/ and do {
	    $opts{file} = shift @ARGV; last;
	};
	/^-L$/ and do {
	    $opts{logfile} = shift @ARGV; last;
	};
	/^-U$/ and do {
	    $opts{username} = shift @ARGV; last;
	};	
	do { # default
	    push @args, $arg;
	};
    }
}
# Finally replace current program with target driver binary
my $cfg = $dbconf{$dbname};
my $drv = $DRIVERS{$cfg->{type}};
unshift @args, $drv->{run}; # CLI binary
push @args, (
    $drv->{opt}{host}     => $cfg->{host},
    $drv->{opt}{dbname}   => $cfg->{name}
    #$drv->{opt}{username} => $cfg->{user}
);
push @args,(defined $opts{username} ? $opts{username} : $cfg->{user});
push @args,$drv->{opt}{command},$opts{command} if defined $opts{command};
push @args,$drv->{opt}{file},$opts{file} if defined $opts{file};
push @args,$drv->{opt}{logfile},$opts{logfile} if defined $opts{logfile};

exec @args or die "Couldn't exec $args[0]: $!\n";
