<?php   
require_once 'query.php'; // contains the DBQuery object

/**
 * Query Exception
 *
 * Thrown by the {@link DBQuery} object if an error occurs while
 * attempting to execute a query.
 *
 */
class QueryException extends Exception
{
    /**
     * Query Text
     *
     * @var string $QueryText;
     */
    protected $QueryText;

    /**
     * Error Number / Code from the Database
     *
     * @var string $ErrorCode
     */ 
    protected $ErrorNumber;

    /**
     * Error Message from the Database
     *
     * @var string $ErrorMessage
     */
    protected $ErrorMessage;
        
    /**
     * Class constructor
     *
     * @param DBQuery $db Query object which threw this exception.
     */
    public function __construct(DBQuery $query)
    {
        /* get the callign stack */
        $backtrace = $this->GetTrace();

        /* set the line and file - to the location where the error actually occured */
        if (count($backtrace) > 0) {
            $x = 1;

            /* if the query class was inherited we need to disregard the calls by the classes descendants */
            while((! isset($backtrace[$x]['line'])) ||
                  (isset($backtrace[$x]['class']) && is_subclass_of($backtrace[$x]['class'], 'DBQuery')) ||
                  (strpos(strtolower(@$backtrace[$x]['function']), 'call_user_func')) !== false ) {

                /* loop while there is no line number or the function called is a descendant of the DBQuery class */
                ++$x;
                
                /* if we reach the end of the stack, we use the first caller */
                if (($x) >= count($backtrace)) {
                    $x = count($backtrace);
                    break;
                }
            }               
    
            /* if the above loop mader at least on iteration, we reduce it by 1 to find the actual line of code
               which caused the error */
            if ($x != 1) {
                $x -= 1;
            }
            
            /* finally we can set the file and line numbers, which should reflect the SQL statement which caused the error */
            $this->line = $backtrace[$x]['line'];
            $this->file = $backtrace[$x]['file'];
        }
        

        $this->QueryText = $query->getCompiledQuery();
        $this->ErrorNumber = $query->getDB()->errno();
        $this->ErrorMessage = $query->getDB()->error();
            

        /* call the superclass Exception constructor */
        parent::__construct('Query Error', 0);
    }    
        
    /**
     * Get Query Text
     *
     * @return string Query Text
     */
    public function GetQueryText()
    {
        return $this->QueryText;
    }

    /**
     * Get Error Number
     *
     * @return string Error Number
     */
    public function GetErrorNumber()
    {
        return $this->ErrorNumber;
    }

    /**
     * Get Error Message
     *
     * @return string Error Message
     */
     public function GetErrorMessage()
     {
         return $this->ErrorMessage;
     }
        
     /**
      * Called when the object is casted to a string.
      * @return string
      */
     public function __toString()
     {
         $output = "Query Error in {$this->file} on line {$this->line}\n\n";
         $output .= "Query: {$this->QueryText}\n";
         $output .= "Error: {$this->ErrorMessage} ({$this->ErrorNumber})\n\n";            
            
         return $output;
    }

}
// vim: expandtab softtabstop=4 tabstop=4 shiftwidth=4
?>
