package DBIEasy::postgresql;

use strict;
use warnings;
use Data::Dumper;

use base 'DBIEasy';

my $queryTimeout	= 300;

sub getDSN {
	my $self	= shift;

	return (
		'DBI:Pg:' .
		'database=' . $self->dbname .
		';host=' . $self->dbhost,
		$self->dbuser, $self->dbpass
	);
}

sub checkIfTableExists {
	my $self	= shift;
	my $dbh		= $self->dbh;
	my $table	= lc($self->TABLE);

	my @tables	= $dbh->tables(undef, undef, $table);
	unless (grep {/^("?[^\.\s]+"?.)?"?$table"?$/} @tables) {
		if ($self->SETUPTABLE) {
			$self->_carp("Table '$table' doesn't exist, try to create it...\n");
			my $createStmt	= "CREATE TABLE `$table` (" . $self->CREATETABLE . ') ENGINE=InnoDB DEFAULT CHARSET=utf8';
			$dbh->do($createStmt)	or $self->_croak($dbh->errstr);
			
			my @tables	= $dbh->tables(undef, undef, $table);
			unless (grep {/^(`?$self->{dbname}`?.)?`?$table`?$/} @tables) {
				$self->_croak("Sorry, after creating the Table '$table', it isn't there?");
				return 0;
			}
		} else {
			$self->_croak("Table '$table' doesn't exist!");
			return 0;
		}
	}
	return 1;
}

sub getPK {
	my $self	= shift;
	my $dbh		= $self->dbh;
	my $table	= lc($self->TABLE);
	my @PKs		= ();

	my $sth = $dbh->prepare(qq{
SELECT
        f.attname AS pk
FROM
        pg_attribute f
        JOIN pg_class c ON c.oid = f.attrelid
        LEFT JOIN pg_constraint p ON p.conrelid = c.oid AND f.attnum = ANY ( p.conkey )
WHERE
        c.relkind = 'r'::char
        AND p.contype = 'p'
        AND c.relname = ?
        AND f.attnum > 0
	});
  $sth->execute($table);
	$self->_croak($dbh->errstr) if $dbh->errstr;
  if ($sth) {
		my $primKeys	= $sth->fetchall_arrayref({});
		foreach (@{$primKeys}) {
			push @PKs, $_->{pk};
		}
  }
	if ($#PKs == -1) {
		$self->_croak("No Primary Keys in Table '$table'!");
	} else {
		return \@PKs;
	}
}

sub getColoumns {
	my $self	= shift;
	my $dbh		= $self->dbh;
	my $table	= lc($self->TABLE);
	
	my $sth	= $dbh->prepare(qq{
SELECT
	f.attname AS name 
FROM
	pg_attribute f 
	JOIN pg_class c ON c.oid = f.attrelid 
WHERE
	c.relkind = 'r'::char 
	AND c.relname = ?
	AND f.attnum > 0
	});
	$sth->execute($table);
	$self->_croak($dbh->errstr) if $dbh->errstr;

	my $cols	= $sth->fetchall_arrayref({});
	if ($#{$cols} > -1) {
		return map {$_->{name}} @{$cols};
	} else {
		$self->_carp("Sorry, no Columns found!");
		return ();
	}
}

sub checkForOldHandles {
	my $self	= shift;
	my $dbh		= shift;

	my $superUser	= ${$dbh->selectall_arrayref(qq{
		SELECT	usesuper 
		FROM		pg_user
		WHERE		usename=?
	}, { Slice => {} }, $self->dbuser)}[0];

	# Killing old queries only makes sense if database user has superuser rights
	return unless defined $superUser && $superUser->{usesuper};

	my $sth_sh_proc	= $dbh->prepare(q{
		SELECT 
			EXTRACT(EPOCH FROM query_start)::integer as query_start,
			procpid
		FROM
			pg_stat_activity
		WHERE
			current_query='idle in transaction'
	});
	my $sth_kill		= $dbh->prepare("SELECT pg_cancel_backend(?)");

	unless ($sth_sh_proc->execute()) {
		_carp("Unable to execute show procs [" . $dbh->errstr() . "]");
		return 0;
	}

	while (my $row = $sth_sh_proc->fetchrow_hashref()) {
		my $queryAge	= time - $row->{query_start};
		if ($queryAge > $queryTimeout) {
			my $id	= $row->{procpid};
			$sth_kill->execute($id);
		}
	}

	return 1;
}

sub mkCaseSensitive {
	my $self			= shift;
	my @whereStr	= @_;

	# postgresql is case sensitive by default

	return @whereStr;
}

sub _log {
	DBIEasy::_log(@_);
}

sub _carp {
	DBIEasy::_carp(@_);
}

sub _croak {
	DBIEasy::_croak(@_);
}

1;

# vim:ts=2:sts=2:sw=2
