package Db::Connection; use strict; use Logging; use Db::MysqlDbiBackend; use Db::MysqlShellBackend; use Db::DbiBackend; use Db::PostgresqlDbiBackend; use Db::PostgresqlShellBackend; use StopWatch; use vars qw|$QUIET $UsePostgreShellBackendAsSudo $backend|; $QUIET = 1; $UsePostgreShellBackendAsSudo = 0; #Set this if you want use Postgre shell backend runnig by sudo # # Required parameters: 'type', 'name', 'user', 'password'. # # 'type' is the 'mysql' or 'postgresql'. # # Optional parameters: # 'host' - database host name, if remote. # 'nodbi' - disable DBI modules probe and use. # # mysql: # # Optional parameters: # 'socket' - mysql socket to connect to DB. Disables the DBI modules use. # 'preload_dirs' - directories to add to LD_PRELOAD_PATH to connect to DB. # Also disables the DBI modules use. # # postgresql: # # No additional parameters. # sub getConnection { my $be = getBackend(@_); if ($be) { Logging::info("New connection: " . $be->description()); return Db::Connection->new($be); } } sub _getDbiBackend { my ($type, %params) = @_; if ($type eq 'mysql') { return Db::MysqlDbiBackend->new(%params); } if ($type eq 'postgresql') { return Db::PostgresqlDbiBackend->new(%params); } die "Unknown DBMS type: $type"; } sub _getShellBackend { my ($type, %params) = @_; if ($type eq 'mysql') { return Db::MysqlShellBackend->new(%params); } if ($type eq 'postgresql') { return Db::PostgresqlShellBackend->new(%params); } die "Unknown DBMS type: $type"; } sub getBackend { my (%params) = @_; my $type = $params{type}; delete $params{type}; my $dbi = 1; if( $type eq 'postgresql' and $UsePostgreShellBackendAsSudo ){ $dbi = 0; Db::PostgresqlShellBackend::set_sudo( 1 ); } if (defined $params{nodbi}) { $dbi = 0; delete $params{nodbi}; } if ($dbi and !defined $params{preload_dirs} and !defined $params{socket}) { my $conn = _getDbiBackend($type, %params); return $conn if $conn->connect(); if (!defined $params{host}) { my $conn = _getDbiBackend($type, %params, 'host' => 'localhost'); return $conn if $conn->connect(); } } delete $params{nodbi}; my $conn = _getShellBackend($type, %params); return $conn if $conn->connect(); if (!defined $params{host}) { my $conn = _getShellBackend($type, %params, 'host' => 'localhost'); return $conn if $conn->connect(); } } sub getDumpCmdLine { $backend = getBackend(@_, 'nodbi' => 1); return $backend->dumpCmdline(); } sub getFileToRemove { if (ref($backend) =~ /Db::MysqlShellBackend/) { return $backend->getFileToRemove(); } } # # Connection itself # sub new { my $self = {}; bless($self, shift); $self->_init(@_); return $self; } sub _init { my ($self, $backend) = @_; $self->{backend} = $backend; } sub startCollectStatistics ( $ ) { my $self = shift(@_); $self->{collectStatistics} = 1; $self->{statistics}->{sqlTime} = 0; $self->{stopWatch} = StopWatch->new(); } sub stopCollectStatistics ( $ ) { my $self = shift(@_); $self->{collectStatistics} = 0; delete $self->{statistics}; delete $self->{stopWatch}; } sub getStatistics ( $ ) { my $self = shift(@_); return $self->{statistics}; } sub disconnect { my ($self) = @_; return $self->{backend}->disconnect(); } sub execute { my ($self, $sql, $quiet) = @_; if (defined $self->{sql}) { Logging::debug("Unfinished SQL query: ", $self->{sql}); delete $self->{sql}; } Logging::trace("SQL: $sql"); if ($self->{collectStatistics}) { $self->{stopWatch}->createMarker("sql"); } my $res = $self->{backend}->execute($sql, $quiet); if ($self->{collectStatistics}) { $self->{statistics}->{sqlTime} += $self->{stopWatch}->getDiff("sql"); $self->{stopWatch}->releaseMarker("sql"); } $self->{sql} = $sql if $res; return $res; } sub rownum { my ($self) = @_; if ($self->{collectStatistics}) { $self->{stopWatch}->createMarker("sql"); } my $ret = $self->{backend}->rownum(); if ($self->{collectStatistics}) { $self->{statistics}->{sqlTime} += $self->{stopWatch}->getDiff("sql"); $self->{stopWatch}->releaseMarker("sql"); } return $ret; } sub execute_rownum { my ($self, $sql, $quiet) = @_; return if !$self->execute($sql, $quiet); return $self->rownum(); } sub fetchrow { my ($self) = @_; if ($self->{collectStatistics}) { $self->{stopWatch}->createMarker("sql"); } my $ret = $self->{backend}->fetchrow(); if ($self->{collectStatistics}) { $self->{statistics}->{sqlTime} += $self->{stopWatch}->getDiff("sql"); $self->{stopWatch}->releaseMarker("sql"); } return $ret; } sub fetchhash { my ($self) = @_; if ($self->{collectStatistics}) { $self->{stopWatch}->createMarker("sql"); } my $ret = $self->{backend}->fetchhash(); if ($self->{collectStatistics}) { $self->{statistics}->{sqlTime} += $self->{stopWatch}->getDiff("sql"); $self->{stopWatch}->releaseMarker("sql"); } return $ret; } sub finish { my ($self) = @_; delete $self->{sql}; if ($self->{collectStatistics}) { $self->{stopWatch}->createMarker("sql"); } my $ret = $self->{backend}->finish(); if ($self->{collectStatistics}) { $self->{statistics}->{sqlTime} += $self->{stopWatch}->getDiff("sql"); $self->{stopWatch}->releaseMarker("sql"); } return $ret; } sub ping { my ($self) = @_; if ($self->{collectStatistics}) { $self->{stopWatch}->createMarker("sql"); } my $ret = $self->{backend}->ping(); if ($self->{collectStatistics}) { $self->{statistics}->{sqlTime} += $self->{stopWatch}->getDiff("sql"); $self->{stopWatch}->releaseMarker("sql"); } return $ret; } sub getName { my ($self) = @_; return $self->{backend}->{name}; } sub getPassword { my ($self) = @_; return $self->{backend}->{password}; } sub getUser { my ($self) = @_; return $self->{backend}->{user}; } sub getType { my ($self) = @_; return $self->{backend}->{type}; } 1;