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

use strict;
use Db::DbiBackend;
use Db::MysqlUtils;

use vars qw|@ISA|;

@ISA = qw|Db::DbiBackend|;

#
# 'name', 'user', 'password'[, 'host'][, 'socket'][, 'port'][, 'utf8names']
#

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

  $self->SUPER::_init(%params, 'type'=>'mysql');

  if (defined $params{host} and defined $params{socket}) {
	return "socket & host are mutually exclusive";
  }

  $self->{socket} = $params{socket} if defined $params{socket};
  $self->{port} = $params{port} if defined $params{port};
  $self->{utf8names} = $params{utf8names} if defined $params{utf8names};
  $self->{connRetries} = (defined $params{connRetries}) ? $params{connRetries} : 0;
}

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

  my $address = $self->SUPER::_composeDbiAddress();
  $address .= ";mysql_socket=$self->{socket}" if defined $self->{socket};
  $address .= ";port=$self->{port}" if defined $self->{port};
  # $address .= ';mysql_server_prepare=1'; # do not turn on prepared statements because of issues in perl-DBD-MySQL (https://rt.cpan.org/Public/Bug/Display.html?id=75570, https://rt.cpan.org/Public/Bug/Display.html?id=80394)
  return $address;
}

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

  my $retry = 0;
  while (!$self->SUPER::connect()) {
    return if (++$retry > $self->{connRetries});
    sleep 1;
    Logging::debug("Connection to mysql database failed. Try again...");
  }

  if ($self->{utf8names} && Db::MysqlUtils::doesSupportCharacterSets($self)) {
    $self->execute(Db::MysqlUtils::getCharacterSetsSupportSql());
    $self->execute(Db::MysqlUtils::getNamesCharacterSetsSupportSql());
  }

  return 1;
}

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 && $DBI::err != 2006) {
    Logging::warning("Unable to execute SQL: $DBI::errstr. SQL query: $sql");
    $self->_set_errstr("Unable to execute SQL: $DBI::errstr");
    return;
  }

  return $res;
}

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

  my $res = $self->_execute($sql, $quiet, @params);
  return $res if $res;
  #
  # Reconnect on timeout
  #
  Logging::debug("Timeout occured during mysql query. Reconnecting.");
  $self->{dbh}->disconnect();
  die if !$self->connect();

  return $self->_execute($sql, $quiet, @params);
}

1;
