# Copyright 1999-2016. Parallels IP Holdings GmbH. All Rights Reserved.
package Db::PostgresqlShellBackend;

use strict;
use Db::ShellBackend;
use AgentConfig;

use vars qw|@ISA|;

@ISA = qw|Db::ShellBackend|;

my $useSudo = 0;

sub set_sudo{
  $useSudo = $_[0];
}

sub description {
  my ($self) = @_;
  return "postgresql shell connection. " . $self->SUPER::description();
}

sub _escapeShell {
  my ($value) = @_;
  $value =~ s/([^a-zA-Z0-9_-])/\\$1/g;
  return $value;
}

sub _getCmd {
  my ($self, $cmd, $additionalOptions) = @_;

  if( $useSudo ){
    $cmd = "sudo -u $self->{user} $cmd";
    $cmd = "$cmd $self->{name}" if $self->{name};
  }
  else{
	  # variable PGDATABASE is used instead of command argument for db names beginning with '-', bug #109219
	  $cmd = 'PGUSER=' . _escapeShell($self->{user}) . " $cmd" if $self->{user};
	  $cmd = 'PGPASSWORD=' . _escapeShell($self->{password}) . " $cmd" if $self->{password};
	  $cmd = 'PGDATABASE=' . _escapeShell($self->{name}) . " $cmd";
  }
  $cmd .= " -h '$self->{host}'" if $self->{host} and $self->{host} ne 'localhost';
  $cmd .= " -p '$self->{port}'" if $self->{port} and $self->{port} ne '5432';
  $cmd .= " $additionalOptions" if $additionalOptions;

  return $cmd;
}

sub connect {
  my ($self) = @_;

  if (!AgentConfig::psqlBin()) {
    $self->_set_errstr("Unable to find psql");
    return;
  }

  $self->{cmdline} = $self->_getCmd(AgentConfig::psqlBin(), "-c");

  if (!AgentConfig::pgdumpBin()) {
    $self->_set_errstr("Unable to find pg_dump");
    return;
  }

  $self->_setDumpCmdline($self->_getCmd(AgentConfig::pgdumpBin(), "-Fc -b -i"));

  return 1;
}

sub execute {
  my ($self, $sql, $quiet, @params) = @_;

  my $resultSql = $self->_getSql($sql, @params);
  if (!defined($resultSql)) {
    $self->_set_errstr(sprintf("Unable to replace placeholders in SQL query: invalid parameters number (%d)\n%s", scalar(@params), $sql));
    return;
  }
  $sql = $resultSql;

  # quote ` from the shell and ' from the string
  $sql =~ s/`/\\`/g;
  $sql =~ s/'/'\\''/g;

  my @out = `$self->{cmdline} '$sql'`;
  chomp @out;

  my @res;

  foreach my $line (@out) {
    next if $line=~/^-[-+]+$/; # skip delimiter
    last if $line=~/^\(\s*\d+\s+\w+\)$/; # footer
    $line=~s/^\s+//;
    $line=~s/\s+$//;
    push @res, [split(/\s*\|\s*/,$line)];
  }

  $self->_set_execute_result(\@res);
  return 1;
}

1;
