arse/includes/core/database.inc.php

140 lines
3.1 KiB
PHP
Raw Permalink Normal View History

<?php
class DatabaseError extends RuntimeException { }
final class Database
implements PackageAware
{
private $connection;
private $package;
private $queries = array( );
public function setPackage( Package $package )
{
if ( $this->package !== null ) {
throw new Exception( 'trying to call setPackage() twice' );
}
$this->package = $package;
}
public function query( $query , $prepare = false )
{
if ( ! $this->connection ) {
$this->connect( );
}
if ( ! array_key_exists( $query , $this->queries )
|| ( $prepare && ! $this->queries[ $query ]->prepared( ) ) ) {
$this->queries[ $query ] = new DBQuery( $this->connection , $query , $prepare );
}
return $this->queries[ $query ];
}
public function commit( )
{
if ( ! $this->connection ) {
return;
}
if ( ! @pg_query( 'COMMIT' ) ) {
throw new DatabaseError( 'COMMIT: ' . pg_last_error( ) );
}
exit( 0 );
}
public function connect( )
{
$host = $this->package->config( 'db/host' , 'localhost' );
$port = $this->package->config( 'db/port' );
$name = $this->package->config( 'db/name' , null , true );
$user = $this->package->config( 'db/user' );
$pass = $this->package->config( 'db/password' );
$cString = array( );
$cString[] = "host=$host";
if ( $port !== null ) {
$cString[] = "port=$port";
}
$cString[] = "dbname=$name";
if ( $user !== null ) {
$cString[] = "user=$user";
}
if ( $pass !== null ) {
$cString[] = "password=$pass";
}
$this->connection = pg_connect( join( ' ' , $cString ) );
if ( ! $this->connection ) {
throw new DatabaseError( 'connection failed' );
}
if ( ! @pg_query( $this->connection , 'BEGIN TRANSACTION' ) ) {
throw new DatabaseError( 'BEGIN TRANSACTION: ' . pg_last_error( ) );
}
}
}
final class DBQuery
{
private static $lastStatementID = 0;
private $connection;
private $query;
private $statement;
public function __construct( $connection , $query , $prepare = false )
{
$this->connection = $connection;
$this->query = $query;
if ( $prepare ) {
$this->statement = 'prep_stmt_' . ( ++ DBQuery::$lastStatementID );
if ( ! pg_prepare( $connection , $this->statement , $query ) ) {
throw new Exception( "unable to prepare statement '$query': " . pg_last_error( ) );
}
} else {
$this->statement = null;
}
}
public function __destruct( )
{
if ( $this->statement !== null ) {
if ( ! pg_query( 'DEALLOCATE ' . $this->statement ) ) {
throw new Exception( "unable to deallocate statement: " . pg_last_error( ) );
}
}
}
public function execute( )
{
$arguments = func_get_args( );
$result = array( );
if ( $this->statement !== null ) {
$pgResult = pg_execute( $this->connection , $this->statement , $arguments );
} else {
$pgResult = pg_query_params( $this->connection , $this->query , $arguments );
}
if ( ! $pgResult ) {
throw new Exception( "query \"{$this->query}\" failed: " . pg_last_error( ) );
}
while ( $row = pg_fetch_object( $pgResult ) ) {
array_push( $result , $row );
}
pg_free_result( $pgResult );
return $result;
}
public function prepared( )
{
return ( $this->statement !== null );
}
}