<?php
class MySQLConnection extends ConnectionCommon
{

    /** Current database (used in mysql_select_db()). */
    private $database;

    /**
     * Connect to a database and log in as the specified user.
     *
     * @param $dsn the data source name (see DB::parseDSN for syntax)
     * @param $flags Any conneciton flags.
     * @access public
     * @throws Exception
     * @return void
     */
    function connect( $dsninfo, $flags = 0 )
    {
//    if (!extension_loaded('mysql')) {
//      throw new Exception('mysql extension not loaded');
//    }

        $this->dsn = $dsninfo;
        $this->flags = $flags;

        //$persistent = ($flags & Creole::PERSISTENT) === Creole::PERSISTENT;
        $persistent = $flags;

        if ( isset( $dsninfo['protocol'] ) && $dsninfo['protocol'] == 'unix' )
        {
            $dbhost = ':' . $dsninfo['socket'];
        }
        else
        {
            $dbhost = $dsninfo['hostspec'] ? $dsninfo['hostspec'] : 'localhost';
            if ( !empty( $dsninfo['port'] ) )
            {
                $dbhost .= ':' . $dsninfo['port'];
            }
        }
        $user = $dsninfo['username'];
        $pw = $dsninfo['password'];

        $encoding = !empty( $dsninfo['encoding'] ) ? $dsninfo['encoding'] : null;

        $connect_function = $persistent ? 'mysql_pconnect' : 'mysql_connect';

        @ini_set( 'track_errors', true );
        if ( $dbhost && $user && $pw )
        {
            $conn = @$connect_function( $dbhost, $user, $pw );
        }
        elseif ( $dbhost && $user )
        {
            $conn = @$connect_function( $dbhost, $user );
        }
        elseif ( $dbhost )
        {
            $conn = @$connect_function( $dbhost );
        }
        else
        {
            $conn = false;
        }
        @ini_restore( 'track_errors' );
        if ( empty( $conn ) )
        {
            if ( ($err = @mysql_error()) != '' )
            {
                throw new Exception( "connect failed: ". $err );
            }
            elseif ( empty( $php_errormsg ) )
            {
                throw new Exception( "connect failed" );
            }
            else
            {
                throw new Exception( "connect failed", $php_errormsg );
            }
        }

        if ( $dsninfo['database'] )
        {
            if ( !@mysql_select_db( $dsninfo['database'], $conn ) )
            {
                switch ( mysql_errno( $conn ) )
                {
                    case 1049:
                        $exc = new Exception( "no such database", mysql_error( $conn ) );
                        break;
                    case 1044:
                        $exc = new Exception( "access violation", mysql_error( $conn ) );
                        break;
                    default:
                        $exc = new Exception( "cannot select database", mysql_error( $conn ) );
                }

                throw $exc;
            }
            // fix to allow calls to different databases in the same script
            $this->database = $dsninfo['database'];
        }

        $this->dblink = $conn;

        if ( $encoding )
        {
            //$this->executeUpdate( "SET NAMES " . $encoding );
            mysql_set_charset( $encoding, $conn );
        }
    }

    /**
     * @see Connection::disconnect()
     */
    function close()
    {
        $ret = mysql_close( $this->dblink );
        $this->dblink = null;
        return $ret;
    }

    /**
     * @see Connection::applyLimit()
     */
    public function applyLimit( &$sql, $offset, $limit )
    {
        if ( $limit > 0 )
        {
            $sql .= " LIMIT " . ($offset > 0 ? $offset . ", " : "") . $limit;
        }
        else if ( $offset > 0 )
        {
            $sql .= " LIMIT " . $offset . ", 18446744073709551615";
        }
    }

    /**
     * @see Connection::executeQuery()
     */
    function executeQuery( $sql, $fetchmode = null )
    {
        $this->lastQuery = $sql;
        if ( $this->database )
        {
            if ( !@mysql_select_db( $this->database, $this->dblink ) )
            {
                throw new Exception( 'No database selected', mysql_error( $this->dblink ) );
            }
        }
        $result = @mysql_query( $sql, $this->dblink );
        if ( !$result )
        {
            throw new Exception( 'Could not execute query', mysql_error( $this->dblink ), $sql );
        }
        return new MySQLResultSet( $this, $result, $fetchmode );
    }

    /**
     * @see Connection::executeUpdate()
     */
    function executeUpdate( $sql )
    {
        $this->lastQuery = $sql;

        if ( $this->database )
        {
            if ( !@mysql_select_db( $this->database, $this->dblink ) )
            {
                throw new Exception( 'No database selected', mysql_error( $this->dblink ) );
            }
        }

        $result = @mysql_query( $sql, $this->dblink );
        if ( !$result )
        {
            throw new Exception( 'Could not execute update', mysql_error( $this->dblink ), $sql );
        }
        return ( int ) mysql_affected_rows( $this->dblink );
    }

    /**
     * Start a database transaction.
     * @throws Exception
     * @return void
     */
    protected function beginTrans()
    {
        $result = @mysql_query( 'SET AUTOCOMMIT=0', $this->dblink );
        $result = @mysql_query( 'BEGIN', $this->dblink );
        if ( !$result )
        {
            throw new Exception( 'Could not begin transaction', mysql_error( $this->dblink ) );
        }
    }

    /**
     * Commit the current transaction.
     * @throws Exception
     * @return void
     */
    protected function commitTrans()
    {
        if ( $this->database )
        {
            if ( !@mysql_select_db( $this->database, $this->dblink ) )
            {
                throw new Exception( 'No database selected', mysql_error( $this->dblink ) );
            }
        }
        $result = @mysql_query( 'COMMIT', $this->dblink );
        $result = @mysql_query( 'SET AUTOCOMMIT=1', $this->dblink );
        if ( !$result )
        {
            throw new Exception( 'Can not commit transaction', mysql_error( $this->dblink ) );
        }
    }

    /**
     * Roll back (undo) the current transaction.
     * @throws Exception
     * @return void
     */
    protected function rollbackTrans()
    {
        if ( $this->database )
        {
            if ( !@mysql_select_db( $this->database, $this->dblink ) )
            {
                throw new Exception( 'No database selected', mysql_error( $this->dblink ) );
            }
        }
        $result = @mysql_query( 'ROLLBACK', $this->dblink );
        $result = @mysql_query( 'SET AUTOCOMMIT=1', $this->dblink );
        if ( !$result )
        {
            throw new Exception( 'Could not rollback transaction', mysql_error( $this->dblink ) );
        }
    }

    /**
     * Gets the number of rows affected by the data manipulation
     * query.
     *
     * @return int Number of rows affected by the last query.
     */
    function getUpdateCount()
    {
        return ( int ) @mysql_affected_rows( $this->dblink );
    }

}
