<?php
/**
 * A class for establishing db connections.
 *
 * This class is a thin layer over pdo connection. It provides a fluent
 * interface and a few convenient functions.
 */
class db_connection extends pdo
{
    ////////////////////////////////////////////////////////////////////////////
    // Construct and destruct functions.
    
    /**
     * @param string $dsn The dsn.
     * @param string (optional) $user The user.
     * @param string (optional) $password The password.
     * @param array (optional) $option The connection options.
     * @throws unexpectedvalueexception If the pdo error mode could not be set
     * to exception.
     */
    public function __construct($dsn, $user = null, $password = null, $option = array())
    {
        parent::__construct($dsn, $user, $password, $option);
        
        if (!$this->setattribute(pdo::ATTR_ERRMODE, pdo::ERRMODE_EXCEPTION))
        {
            throw new unexpectedvalueexception('Pdo attribute \'pdo::ATTR_ERRMODE\' could not be set to \'pdo::ERRMODE_EXCEPTION\'.');
        }
        
        $this->setattribute(pdo::ATTR_STATEMENT_CLASS, array('db_statement', array()));
        $this->setattribute(pdo::ATTR_CASE, pdo::CASE_LOWER);
    }
    
    ////////////////////////////////////////////////////////////////////////////
    // Overload functions.

    ////////////////////////////////////////////////////////////////////////////
    // Interface functions.

    /**
     * Queries the database.
     * 
     * @param string (optional) $sql The sql query.
     * @param array (optional) $data The parameters.
     * @return db_query/db_statement The query object or query result.
     */
    public function query($sql = null, array $data = array())
    {
        if (func_num_args())
        {
            $statement = null;
            
            if ($data)
            {
                $statement = $this->prepare($sql);
                $statement->execute($data);
            }
            else
            {
                $statement = parent::query($sql);
            }
            
            return $statement;
        }
        else
        {
            $class = 'db_query_' . $this->getattribute(pdo::ATTR_DRIVER_NAME);
            return new $class($this);
        }
    }
    
    /**
     * Begins a transaction.
     * 
     * @return db_connection A fluent interface.
     */
    public function begin()
    {
        $this->begintransaction();
        return $this;
    }
    
    /**
     * Commits a transaction.
     * 
     * @return db_connection A fluent interface.
     */
    public function commit()
    {
        parent::commit();
        return $this;
    }
    
    /**
     * Rollbacks a transaction.
     * 
     * @return db_connection A fluent interface.
     */
    public function rollback()
    {
        parent::rollback();
        return $this;
    }
    
    /**
     * Gets the last id inserted.
     *
     * @return integer The id.
     */
    public function get_last_id($name = null)
    {
        return $this->lastinsertid($name);
    }
    
    ////////////////////////////////////////////////////////////////////////////
    // Internal functions.
}
