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

use strict;
use Db::Backend;
use Logging;
use HelpFuncs;

use vars qw|@ISA|;

@ISA = qw|Db::Backend|;

sub _init {
  my ($self, %params) = @_;

  $self->SUPER::_init(%params);

  $self->{type} = $params{type};
}

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

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

  my $address = "DBI:$self->{type}:dbname=$self->{name}";
  $address .= ";host=$self->{host}" if defined $self->{host};

  return $address;
}

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

  foreach my $requiredModule ('DBI', 'DBD::' . $self->{type}) {
    if (!HelpFuncs::isModuleLoadable($requiredModule)) {
      $self->_set_errstr("Unable to find $requiredModule module");
      return;
    }
  }

  my $address = $self->_composeDbiAddress();

  $self->{dbh} = DBI->connect($address, $self->{user}, $self->{password});

  return 1 if $self->{dbh};

  $self->_set_errstr("Unable to connect to database: $DBI::errstr", $DBI::err);
  return;
}

sub disconnect {
  my ($self) = @_;
  $self->{dbh}->disconnect();
}

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

  $self->{result} = $self->{dbh}->prepare($self->_getSqlTemplate($sql));
  if (!$self->{result}) {
    Logging::warning("Unable to prepare SQL for execution: $DBI::errstr");
    $self->_set_errstr("Unable to prepare SQL ( for execution: $DBI::errstr");
    return;
  }

  my $res = $self->{result}->execute(@params);
  if (!defined $res) {
    Logging::warning("Unable to execute SQL: $DBI::errstr. SQL query: $sql") unless $quiet;
    $self->_set_errstr("Unable to execute SQL: $DBI::errstr");
    return;
  }

  return 1;
}

sub rownum {
  my ($self) = @_;
  return $self->{result}->rows;
}

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

  return $self->{result}->fetchrow_arrayref();
}

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

  my $h = $self->{result}->fetchrow_hashref();
  return if ref($h) eq "HASH" and !%$h;
  return $h;
}

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

  $self->{result}->finish();
}

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

  return $self->{dbh}->ping();
}

sub quote {
  my ($self, $sql) = @_;
  return $self->{dbh}->quote($sql);
}

sub _getSqlTemplate {
  my ($self, $sql) = @_;
  $sql =~ s/'\?'/?/g;
  return $sql;
}

1;
