mirror of
				https://github.com/Icinga/icingaweb2.git
				synced 2025-11-03 20:54:27 +01:00 
			
		
		
		
	Data\Db: rename Query and Connection to Db...
Class names in namespaces should not be chosen as once we didn't have such. The fact that we already did "use Db\Connection as DbConnection" is the best hint that naming was wrong. So this patch renames Db\Connection to Db\DbConnection and does the same with DbQuery. DbQuery has been adjusted to fit our new SimpleQuery and to handle the new Filter implementation.
This commit is contained in:
		
							parent
							
								
									1fbca25d99
								
							
						
					
					
						commit
						db3accc704
					
				@ -57,7 +57,7 @@ database test looks like this:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        /**
 | 
					        /**
 | 
				
			||||||
         * @dataProvider    mysqlDb
 | 
					         * @dataProvider    mysqlDb
 | 
				
			||||||
         * @param           Icinga\Data\Db\Connection    $mysqlDb
 | 
					         * @param           Icinga\Data\Db\DbConnection    $mysqlDb
 | 
				
			||||||
         */
 | 
					         */
 | 
				
			||||||
        public function testSomethingWithMySql($mysqlDb)
 | 
					        public function testSomethingWithMySql($mysqlDb)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
 | 
				
			|||||||
@ -29,24 +29,24 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace Icinga\Authentication\Backend;
 | 
					namespace Icinga\Authentication\Backend;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use \Exception;
 | 
					 | 
				
			||||||
use \Zend_Db_Expr;
 | 
					 | 
				
			||||||
use \Zend_Db_Select;
 | 
					 | 
				
			||||||
use Icinga\Authentication\UserBackend;
 | 
					use Icinga\Authentication\UserBackend;
 | 
				
			||||||
use Icinga\Data\Db\Connection;
 | 
					use Icinga\Data\Db\DbConnection;
 | 
				
			||||||
use Icinga\User;
 | 
					use Icinga\User;
 | 
				
			||||||
use Icinga\Exception\AuthenticationException;
 | 
					use Icinga\Exception\AuthenticationException;
 | 
				
			||||||
 | 
					use Exception;
 | 
				
			||||||
 | 
					use Zend_Db_Expr;
 | 
				
			||||||
 | 
					use Zend_Db_Select;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class DbUserBackend extends UserBackend
 | 
					class DbUserBackend extends UserBackend
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Connection to the database
 | 
					     * Connection to the database
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @var Connection
 | 
					     * @var DbConnection
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    private $conn;
 | 
					    private $conn;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function __construct(Connection $conn)
 | 
					    public function __construct(DbConnection $conn)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $this->conn = $conn;
 | 
					        $this->conn = $conn;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -150,4 +150,4 @@ class DbUserBackend extends UserBackend
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        return ($row !== false) ? $row->count : 0;
 | 
					        return ($row !== false) ? $row->count : 0;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -29,18 +29,18 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace Icinga\Data\Db;
 | 
					namespace Icinga\Data\Db;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use Icinga\Application\Benchmark;
 | 
				
			||||||
 | 
					use Icinga\Data\Db\DbQuery;
 | 
				
			||||||
 | 
					use Icinga\Data\Selectable;
 | 
				
			||||||
 | 
					use Icinga\Exception\ConfigurationError;
 | 
				
			||||||
use PDO;
 | 
					use PDO;
 | 
				
			||||||
use Zend_Config;
 | 
					use Zend_Config;
 | 
				
			||||||
use Zend_Db;
 | 
					use Zend_Db;
 | 
				
			||||||
use Icinga\Application\Benchmark;
 | 
					 | 
				
			||||||
use Icinga\Data\SimpleQuery;
 | 
					 | 
				
			||||||
use Icinga\Data\Selectable;
 | 
					 | 
				
			||||||
use Icinga\Exception\ConfigurationError;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Encapsulate database connections and query creation
 | 
					 * Encapsulate database connections and query creation
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
class Connection implements Selectable
 | 
					class DbConnection implements Selectable
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Connection config
 | 
					     * Connection config
 | 
				
			||||||
@ -207,11 +207,11 @@ class Connection implements Selectable
 | 
				
			|||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Retrieve an array containing all rows of the result set
 | 
					     * Retrieve an array containing all rows of the result set
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @param   SimpleQuery $query
 | 
					     * @param   DbQuery $query
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @return  array
 | 
					     * @return  array
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public function fetchAll(SimpleQuery $query)
 | 
					    public function fetchAll(DbQuery $query)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        Benchmark::measure('DB is fetching All');
 | 
					        Benchmark::measure('DB is fetching All');
 | 
				
			||||||
        $result = $this->dbAdapter->fetchAll($query->getSelectQuery());
 | 
					        $result = $this->dbAdapter->fetchAll($query->getSelectQuery());
 | 
				
			||||||
@ -222,11 +222,11 @@ class Connection implements Selectable
 | 
				
			|||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Fetch the first row of the result set
 | 
					     * Fetch the first row of the result set
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @param   SimpleQuery $query
 | 
					     * @param   DbQuery $query
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @return  mixed
 | 
					     * @return  mixed
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public function fetchRow(SimpleQuery $query)
 | 
					    public function fetchRow(DbQuery $query)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return $this->dbAdapter->fetchRow($query->getSelectQuery());
 | 
					        return $this->dbAdapter->fetchRow($query->getSelectQuery());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -234,12 +234,12 @@ class Connection implements Selectable
 | 
				
			|||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Fetch a column of all rows of the result set as an array
 | 
					     * Fetch a column of all rows of the result set as an array
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @param   SimpleQuery   $query
 | 
					     * @param   DbQuery   $query
 | 
				
			||||||
     * @param   int         $columnIndex Index of the column to fetch
 | 
					     * @param   int         $columnIndex Index of the column to fetch
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @return  array
 | 
					     * @return  array
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public function fetchColumn(SimpleQuery $query, $columnIndex = 0)
 | 
					    public function fetchColumn(DbQuery $query, $columnIndex = 0)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return $this->dbAdapter->fetchCol($query->getSelectQuery());
 | 
					        return $this->dbAdapter->fetchCol($query->getSelectQuery());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -247,11 +247,11 @@ class Connection implements Selectable
 | 
				
			|||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Fetch the first column of the first row of the result set
 | 
					     * Fetch the first column of the first row of the result set
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @param   SimpleQuery $query
 | 
					     * @param   DbQuery $query
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @return  string
 | 
					     * @return  string
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public function fetchOne(SimpleQuery $query)
 | 
					    public function fetchOne(DbQuery $query)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return $this->dbAdapter->fetchOne($query->getSelectQuery());
 | 
					        return $this->dbAdapter->fetchOne($query->getSelectQuery());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -261,11 +261,11 @@ class Connection implements Selectable
 | 
				
			|||||||
     *
 | 
					     *
 | 
				
			||||||
     * The first column is the key, the second column is the value.
 | 
					     * The first column is the key, the second column is the value.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @param   SimpleQuery $query
 | 
					     * @param   DbQuery $query
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @return  array
 | 
					     * @return  array
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public function fetchPairs(SimpleQuery $query)
 | 
					    public function fetchPairs(DbQuery $query)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return $this->dbAdapter->fetchPairs($query->getSelectQuery());
 | 
					        return $this->dbAdapter->fetchPairs($query->getSelectQuery());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
							
								
								
									
										238
									
								
								library/Icinga/Data/Db/DbQuery.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										238
									
								
								library/Icinga/Data/Db/DbQuery.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,238 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Icinga\Data\Db;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use Icinga\Data\SimpleQuery;
 | 
				
			||||||
 | 
					use Icinga\Application\Benchmark;
 | 
				
			||||||
 | 
					use Icinga\Data\Filter\FilterOperator;
 | 
				
			||||||
 | 
					use Icinga\Data\Filter\FilterOr;
 | 
				
			||||||
 | 
					use Icinga\Data\Filter\FilterAnd;
 | 
				
			||||||
 | 
					use Icinga\Data\Filter\FilterNot;
 | 
				
			||||||
 | 
					use Zend_Db_Select;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Database query class
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					class DbQuery extends SimpleQuery
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @var Zend_Db_Adapter_Abstract
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    protected $db;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Select query
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @var Zend_Db_Select
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    protected $select;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Whether to use a subquery for counting
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * When the query is distinct or has a HAVING or GROUP BY clause this must be set to true
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @var bool
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    protected $useSubqueryCount = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Set the count maximum
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * If the count maximum is set, count queries will not count more than that many rows. You should set this
 | 
				
			||||||
 | 
					     * property only for really heavy queries.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @var int
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    protected $maxCount;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Count query result
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * Count queries are only executed once
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @var int
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    protected $count;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected function init()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $this->db = $this->ds->getDbAdapter();
 | 
				
			||||||
 | 
					        parent::init();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function where($condition, $value = null)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // $this->count = $this->select = null;
 | 
				
			||||||
 | 
					        return parent::where($condition, $value);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected function dbSelect()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if ($this->select === null) {
 | 
				
			||||||
 | 
					            $this->select = $this->db->select()->from($this->table, array());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return clone $this->select;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Get the select query
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * Applies order and limit if any
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return Zend_Db_Select
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function getSelectQuery()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $select = $this->dbSelect();
 | 
				
			||||||
 | 
					        $select->columns($this->columns);
 | 
				
			||||||
 | 
					        $this->applyFilterSql($select);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ($this->hasLimit() || $this->hasOffset()) {
 | 
				
			||||||
 | 
					            $select->limit($this->getLimit(), $this->getOffset());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if ($this->hasOrder()) {
 | 
				
			||||||
 | 
					            foreach ($this->getOrder() as $fieldAndDirection) {
 | 
				
			||||||
 | 
					                $select->order(
 | 
				
			||||||
 | 
					                    $fieldAndDirection[0] . ' ' . $fieldAndDirection[1]
 | 
				
			||||||
 | 
					                );
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return $select;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected function applyFilterSql($query)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $where = $this->renderFilter($this->filter);
 | 
				
			||||||
 | 
					        if ($where !== '') {
 | 
				
			||||||
 | 
					            $query->where($where);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected function renderFilter($filter, $level = 0)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $str = '';
 | 
				
			||||||
 | 
					        if ($filter instanceof FilterOperator) {
 | 
				
			||||||
 | 
					            if ($filter instanceof FilterAnd) {
 | 
				
			||||||
 | 
					                $op = ' AND ';
 | 
				
			||||||
 | 
					            } elseif ($filter instanceof FilterOr) {
 | 
				
			||||||
 | 
					                $op = ' OR ';
 | 
				
			||||||
 | 
					            } elseif ($filter instanceof FilterNot) {
 | 
				
			||||||
 | 
					                $op = ' AND ';
 | 
				
			||||||
 | 
					                $str .= ' NOT ';
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                throw new \Exception('Cannot render filter: ' . $filter);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            $parts = array();
 | 
				
			||||||
 | 
					            if (! $filter->isEmpty()) {
 | 
				
			||||||
 | 
					                foreach ($filter->filters() as $f) {
 | 
				
			||||||
 | 
					                    $parts[] = $this->renderFilter($f, $level + 1);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                if ($level > 0) {
 | 
				
			||||||
 | 
					                    $str .= ' (' . implode($op, $parts) . ') ';
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    $str .= implode($op, $parts);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            // TODO: render Filter (Where/like/time...)
 | 
				
			||||||
 | 
					            $str .= $this->whereToSql($filter->getColumn(), $filter->getExpression());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return $str;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected function escapeForSql($value)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // bindParam? bindValue?
 | 
				
			||||||
 | 
					        if (is_array($value)) {
 | 
				
			||||||
 | 
					            $ret = array();
 | 
				
			||||||
 | 
					            foreach ($value as $val) {
 | 
				
			||||||
 | 
					                $ret[] = $this->escapeForSql($val);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return implode(', ', $ret);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            //if (preg_match('/^\d+$/', $value)) {
 | 
				
			||||||
 | 
					            //    return $value;
 | 
				
			||||||
 | 
					            //} else {
 | 
				
			||||||
 | 
					                return $this->db->quote($value);
 | 
				
			||||||
 | 
					            //}
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected function escapeWildcards($value)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return preg_replace('/\*/', '%', $value);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function whereToSql($col, $expression)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (is_array($expression)) {
 | 
				
			||||||
 | 
					            // TODO: Should we support this? Doesn't work for blub*
 | 
				
			||||||
 | 
					            return $col . ' IN (' . $this->escapeForSql($expression) . ')';
 | 
				
			||||||
 | 
					        } elseif (strpos($expression, '*') === false) {
 | 
				
			||||||
 | 
					            return $col . ' = ' . $this->escapeForSql($expression);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            return $col . ' LIKE ' . $this->escapeForSql($this->escapeWildcards($expression));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Get the count query
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return Zend_Db_Select
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function getCountQuery()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
							// TODO: there may be situations where we should clone the "select"
 | 
				
			||||||
 | 
					        $count = $this->dbSelect();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->applyFilterSql($count);
 | 
				
			||||||
 | 
					        if ($this->useSubqueryCount) {
 | 
				
			||||||
 | 
					            $columns = array('cnt' => 'COUNT(*)');
 | 
				
			||||||
 | 
					            return $this->db->select()->from($count, $columns);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if ($this->maxCount !== null) {
 | 
				
			||||||
 | 
					            return $this->db->select()->from($count->limit($this->maxCount));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $count->columns(array('cnt' => 'COUNT(*)'));
 | 
				
			||||||
 | 
					        return $count;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Count all rows of the result set
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return int
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function count()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if ($this->count === null) {
 | 
				
			||||||
 | 
					            Benchmark::measure('DB is counting');
 | 
				
			||||||
 | 
					            $this->count = $this->db->fetchOne($this->getCountQuery());
 | 
				
			||||||
 | 
					            Benchmark::measure('DB finished count');
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return $this->count;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Return the select and count query as a textual representation
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return string A string containing the select and count query, using unix style newlines as linebreaks
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function dump()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return "QUERY\n=====\n"
 | 
				
			||||||
 | 
					        . $this->getSelectQuery()
 | 
				
			||||||
 | 
					        . "\n\nCOUNT\n=====\n"
 | 
				
			||||||
 | 
					        . $this->getCountQuery()
 | 
				
			||||||
 | 
					        . "\n\n";
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @return string
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function __toString()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return (string) $this->getSelectQuery();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,231 +0,0 @@
 | 
				
			|||||||
<?php
 | 
					 | 
				
			||||||
// {{{ICINGA_LICENSE_HEADER}}}
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * This file is part of Icinga Web 2.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Icinga Web 2 - Head for multiple monitoring backends.
 | 
					 | 
				
			||||||
 * Copyright (C) 2013 Icinga Development Team
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * This program is free software; you can redistribute it and/or
 | 
					 | 
				
			||||||
 * modify it under the terms of the GNU General Public License
 | 
					 | 
				
			||||||
 * as published by the Free Software Foundation; either version 2
 | 
					 | 
				
			||||||
 * of the License, or (at your option) any later version.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * This program is distributed in the hope that it will be useful,
 | 
					 | 
				
			||||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
					 | 
				
			||||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
					 | 
				
			||||||
 * GNU General Public License for more details.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * You should have received a copy of the GNU General Public License
 | 
					 | 
				
			||||||
 * along with this program; if not, write to the Free Software
 | 
					 | 
				
			||||||
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @copyright  2013 Icinga Development Team <info@icinga.org>
 | 
					 | 
				
			||||||
 * @license    http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
 | 
					 | 
				
			||||||
 * @author     Icinga Development Team <info@icinga.org>
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
// {{{ICINGA_LICENSE_HEADER}}}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace Icinga\Data\Db;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
use Zend_Db_Select;
 | 
					 | 
				
			||||||
use Icinga\Data\SimpleQuery;
 | 
					 | 
				
			||||||
use Icinga\Application\Benchmark;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Database query class
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
class Query extends SimpleQuery
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * @var Zend_Db_Adapter_Abstract
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    protected $db;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Columns to select
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @var array
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    protected $columns;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Select query
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @var Zend_Db_Select
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    protected $select;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Whether to use a subquery for counting
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * When the query is distinct or has a HAVING or GROUP BY clause this must be set to true
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @var bool
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    protected $useSubqueryCount = false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Set the count maximum
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * If the count maximum is set, count queries will not count more than that many rows. You should set this
 | 
					 | 
				
			||||||
     * property only for really heavy queries.
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @var int
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    protected $maxCount;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Count query result
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * Count queries are only executed once
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @var int
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    protected $count;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    protected function init()
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        $this->db = $this->ds->getDbAdapter();
 | 
					 | 
				
			||||||
        $this->select = $this->db->select();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Set the table and columns to select
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @param   string  $table
 | 
					 | 
				
			||||||
     * @param   array   $columns
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @return  self
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    public function from($table, array $columns = null)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        $this->select->from($table, array());
 | 
					 | 
				
			||||||
        // Don't apply the columns to the select query yet because the count query uses a clone of the select query
 | 
					 | 
				
			||||||
        // but not its columns
 | 
					 | 
				
			||||||
        $this->columns($columns);
 | 
					 | 
				
			||||||
        return $this;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Add a where condition to the query by and
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @param   string  $condition
 | 
					 | 
				
			||||||
     * @param   mixed   $value
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @return  self
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    public function where($condition, $value = null)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        $this->select->where($condition, $value);
 | 
					 | 
				
			||||||
        return $this;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Add a where condition to the query by or
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @param   string  $condition
 | 
					 | 
				
			||||||
     * @param   mixed   $value
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @return  self
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    public function orWhere($condition, $value = null)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        $this->select->orWhere($condition, $value);
 | 
					 | 
				
			||||||
        return $this;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Get the select query
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * Applies order and limit if any
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @return Zend_Db_Select
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    public function getSelectQuery()
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        $select = clone $this->select;
 | 
					 | 
				
			||||||
        $select->columns($this->columns);
 | 
					 | 
				
			||||||
        if ($this->hasLimit() || $this->hasOffset()) {
 | 
					 | 
				
			||||||
            $select->limit($this->getLimit(), $this->getOffset());
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        if ($this->hasOrder()) {
 | 
					 | 
				
			||||||
            foreach ($this->getOrder() as $fieldAndDirection) {
 | 
					 | 
				
			||||||
                $select->order(
 | 
					 | 
				
			||||||
                    $fieldAndDirection[0] . ' ' . $fieldAndDirection[1]
 | 
					 | 
				
			||||||
                );
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        return $select;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Get the count query
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @return Zend_Db_Select
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    public function getCountQuery()
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        $count = clone $this->select;
 | 
					 | 
				
			||||||
        $columns = array('cnt' => 'COUNT(*)');
 | 
					 | 
				
			||||||
        if ($this->useSubqueryCount) {
 | 
					 | 
				
			||||||
            return $this->db->select()->from($count, $columns);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        if ($this->maxCount !== null) {
 | 
					 | 
				
			||||||
            return $this->db->select()->from($count->limit($this->maxCount));
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        $count->columns(array('cnt' => 'COUNT(*)'));
 | 
					 | 
				
			||||||
        return $count;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Count all rows of the result set
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @return int
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    public function count()
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        if ($this->count === null) {
 | 
					 | 
				
			||||||
            Benchmark::measure('DB is counting');
 | 
					 | 
				
			||||||
            $this->count = $this->db->fetchOne($this->getCountQuery());
 | 
					 | 
				
			||||||
            Benchmark::measure('DB finished count');
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        return $this->count;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Return the select and count query as a textual representation
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @return string A string containing the select and count query, using unix style newlines as linebreaks
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    public function dump()
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        return "QUERY\n=====\n"
 | 
					 | 
				
			||||||
        . $this->getSelectQuery()
 | 
					 | 
				
			||||||
        . "\n\nCOUNT\n=====\n"
 | 
					 | 
				
			||||||
        . $this->getCountQuery()
 | 
					 | 
				
			||||||
        . "\n\n";
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * @return string
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    public function __toString()
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        return (string) $this->getSelectQuery();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Set the columns to select
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @param   array $columns
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @return  self
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    public function columns(array $columns)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        $this->columns = $columns;
 | 
					 | 
				
			||||||
        return $this;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,222 +0,0 @@
 | 
				
			|||||||
<?php
 | 
					 | 
				
			||||||
// {{{ICINGA_LICENSE_HEADER}}}
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * This file is part of Icinga Web 2.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Icinga Web 2 - Head for multiple monitoring backends.
 | 
					 | 
				
			||||||
 * Copyright (C) 2013 Icinga Development Team
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * This program is free software; you can redistribute it and/or
 | 
					 | 
				
			||||||
 * modify it under the terms of the GNU General Public License
 | 
					 | 
				
			||||||
 * as published by the Free Software Foundation; either version 2
 | 
					 | 
				
			||||||
 * of the License, or (at your option) any later version.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * This program is distributed in the hope that it will be useful,
 | 
					 | 
				
			||||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
					 | 
				
			||||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
					 | 
				
			||||||
 * GNU General Public License for more details.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * You should have received a copy of the GNU General Public License
 | 
					 | 
				
			||||||
 * along with this program; if not, write to the Free Software
 | 
					 | 
				
			||||||
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @copyright  2013 Icinga Development Team <info@icinga.org>
 | 
					 | 
				
			||||||
 * @license    http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
 | 
					 | 
				
			||||||
 * @author     Icinga Development Team <info@icinga.org>
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
// {{{ICINGA_LICENSE_HEADER}}}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace Icinga\Data\Db;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
use Icinga\Data\SimpleQuery;
 | 
					 | 
				
			||||||
use Icinga\Filter\Query\Tree;
 | 
					 | 
				
			||||||
use Icinga\Filter\Query\Node;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Converter class that takes a query tree and creates an SQL Query from it's state
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
class TreeToSqlParser
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * The query class to use as the base for converting
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @var SimpleQuery
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    private $query;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * The type of the filter (WHERE or HAVING, depending whether it's an aggregate query)
 | 
					 | 
				
			||||||
     * @var string
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    private $type = 'WHERE';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Create a new converter from this query
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @param   SimpleQuery   $query      The query to use for conversion
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    public function __construct(SimpleQuery $query)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        $this->query = $query;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Return the SQL equivalent fo the given text operator
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @param  String $operator     The operator from the query node
 | 
					 | 
				
			||||||
     * @return string               The operator for the sql query part
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    private function getSqlOperator($operator, array $right)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        switch($operator) {
 | 
					 | 
				
			||||||
            case Node::OPERATOR_EQUALS:
 | 
					 | 
				
			||||||
                if (count($right) > 1) {
 | 
					 | 
				
			||||||
                    return 'IN';
 | 
					 | 
				
			||||||
                } else {
 | 
					 | 
				
			||||||
                    foreach ($right as $r) {
 | 
					 | 
				
			||||||
                        if (strpos($r, '*') !== false) {
 | 
					 | 
				
			||||||
                            return 'LIKE';
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                    return '=';
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            case Node::OPERATOR_EQUALS_NOT:
 | 
					 | 
				
			||||||
                if (count($right) > 1) {
 | 
					 | 
				
			||||||
                    return 'NOT IN';
 | 
					 | 
				
			||||||
                } else {
 | 
					 | 
				
			||||||
                    return 'NOT LIKE';
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            default:
 | 
					 | 
				
			||||||
                return $operator;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Convert a Query Tree node to an sql string
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @param Node $node    The node to convert
 | 
					 | 
				
			||||||
     * @return string       The sql string representing the node's state
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    private function nodeToSqlQuery(Node $node)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        if ($node->type !== Node::TYPE_OPERATOR) {
 | 
					 | 
				
			||||||
            return $this->parseConjunctionNode($node);
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            return $this->parseOperatorNode($node);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Parse an AND or OR node to an sql string
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @param Node $node        The AND/OR node to parse
 | 
					 | 
				
			||||||
     * @return string           The sql string representing this node
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    private function parseConjunctionNode(Node $node)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        $queryString =  '';
 | 
					 | 
				
			||||||
        $leftQuery = $node->left !== null ? $this->nodeToSqlQuery($node->left) : '';
 | 
					 | 
				
			||||||
        $rightQuery = $node->right !== null ? $this->nodeToSqlQuery($node->right) : '';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if ($leftQuery != '') {
 | 
					 | 
				
			||||||
            $queryString .= $leftQuery . ' ';
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if ($rightQuery != '') {
 | 
					 | 
				
			||||||
            $queryString .= (($queryString !== '') ? $node->type . ' ' : ' ') . $rightQuery;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        return $queryString;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Parse an operator node to an sql string
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @param Node $node        The operator node to parse
 | 
					 | 
				
			||||||
     * @return string           The sql string representing this node
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    private function parseOperatorNode(Node $node)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        if (!$this->query->isValidFilterTarget($node->left) && $this->query->getMappedField($node->left)) {
 | 
					 | 
				
			||||||
            return '';
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        $this->query->requireColumn($node->left);
 | 
					 | 
				
			||||||
        $queryString = '(' . $this->query->getMappedField($node->left) . ')';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if ($this->query->isAggregateColumn($node->left)) {
 | 
					 | 
				
			||||||
            $this->type = 'HAVING';
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        $queryString .= ' ' . (is_integer($node->right) ?
 | 
					 | 
				
			||||||
                $node->operator : $this->getSqlOperator($node->operator, $node->right)) . ' ';
 | 
					 | 
				
			||||||
        $queryString = $this->addValueToQuery($node, $queryString);
 | 
					 | 
				
			||||||
        return $queryString;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Convert a node value to it's sql equivalent
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * This currently only detects if the node is in the timestring context and calls strtotime if so and it replaces
 | 
					 | 
				
			||||||
     * '*' with '%'
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @param Node $node                The node to retrieve the sql string value from
 | 
					 | 
				
			||||||
     * @return String|int               The converted and quoted value
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    private function addValueToQuery(Node $node, $query) {
 | 
					 | 
				
			||||||
        $values = array();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        foreach ($node->right as $value)  {
 | 
					 | 
				
			||||||
            if ($node->operator === Node::OPERATOR_EQUALS || $node->operator === Node::OPERATOR_EQUALS_NOT) {
 | 
					 | 
				
			||||||
                $value = str_replace('*', '%', $value);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            if ($this->query->isTimestamp($node->left)) {
 | 
					 | 
				
			||||||
                $node->context = Node::CONTEXT_TIMESTRING;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            if ($node->context === Node::CONTEXT_TIMESTRING && !is_numeric($value)) {
 | 
					 | 
				
			||||||
                $value = strtotime($value);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            if (preg_match('/^\d+$/', $value)) {
 | 
					 | 
				
			||||||
                $values[] = $value;
 | 
					 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                $values[] = $this->query->getDatasource()->getConnection()->quote($value);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        $valueString = join(',', $values);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (count($values) > 1) {
 | 
					 | 
				
			||||||
            return $query . '( '. $valueString . ')';
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        return $query . $valueString;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Apply the given tree to the query, either as where or as having clause
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @param Tree $tree                        The tree representing the filter
 | 
					 | 
				
			||||||
     * @param \Zend_Db_Select $baseQuery        The query to apply the filter on
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    public function treeToSql(Tree $tree, $baseQuery)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        if ($tree->root == null) {
 | 
					 | 
				
			||||||
            return;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        $sql = $this->nodeToSqlQuery($tree->normalizeTree($tree->root));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if ($this->filtersAggregate()) {
 | 
					 | 
				
			||||||
            $baseQuery->having($sql);
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            $baseQuery->where($sql);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Return true if this is an filter that should be applied after aggregation
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @return bool         True when having should be used, otherwise false
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    private function filtersAggregate()
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        return $this->type === 'HAVING';
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -33,7 +33,7 @@ use Icinga\Exception\ProgrammingError;
 | 
				
			|||||||
use Zend_Config;
 | 
					use Zend_Config;
 | 
				
			||||||
use Icinga\Util\ConfigAwareFactory;
 | 
					use Icinga\Util\ConfigAwareFactory;
 | 
				
			||||||
use Icinga\Exception\ConfigurationError;
 | 
					use Icinga\Exception\ConfigurationError;
 | 
				
			||||||
use Icinga\Data\Db\Connection as DbConnection;
 | 
					use Icinga\Data\Db\DbConnection;
 | 
				
			||||||
use Icinga\Protocol\Livestatus\Connection as LivestatusConnection;
 | 
					use Icinga\Protocol\Livestatus\Connection as LivestatusConnection;
 | 
				
			||||||
use Icinga\Protocol\Statusdat\Reader as StatusdatReader;
 | 
					use Icinga\Protocol\Statusdat\Reader as StatusdatReader;
 | 
				
			||||||
use Icinga\Protocol\Ldap\Connection as LdapConnection;
 | 
					use Icinga\Protocol\Ldap\Connection as LdapConnection;
 | 
				
			||||||
 | 
				
			|||||||
@ -31,7 +31,7 @@ namespace Icinga\Test {
 | 
				
			|||||||
    use Icinga\Application\Icinga;
 | 
					    use Icinga\Application\Icinga;
 | 
				
			||||||
    use Icinga\Util\DateTimeFactory;
 | 
					    use Icinga\Util\DateTimeFactory;
 | 
				
			||||||
    use Icinga\Data\ResourceFactory;
 | 
					    use Icinga\Data\ResourceFactory;
 | 
				
			||||||
    use Icinga\Data\Db\Connection;
 | 
					    use Icinga\Data\Db\DbConnection;
 | 
				
			||||||
    use Icinga\User\Preferences;
 | 
					    use Icinga\User\Preferences;
 | 
				
			||||||
    use Icinga\Web\Form;
 | 
					    use Icinga\Web\Form;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -193,7 +193,7 @@ namespace Icinga\Test {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /**
 | 
					        /**
 | 
				
			||||||
         * Creates an array of Icinga\Data\Db\Connection
 | 
					         * Creates an array of Icinga\Data\Db\DbConnection
 | 
				
			||||||
         *
 | 
					         *
 | 
				
			||||||
         * @param   string $name
 | 
					         * @param   string $name
 | 
				
			||||||
         *
 | 
					         *
 | 
				
			||||||
@ -215,7 +215,7 @@ namespace Icinga\Test {
 | 
				
			|||||||
        /**
 | 
					        /**
 | 
				
			||||||
         * PHPUnit provider for mysql
 | 
					         * PHPUnit provider for mysql
 | 
				
			||||||
         *
 | 
					         *
 | 
				
			||||||
         * @return Connection
 | 
					         * @return DbConnection
 | 
				
			||||||
         */
 | 
					         */
 | 
				
			||||||
        public function mysqlDb()
 | 
					        public function mysqlDb()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
@ -225,7 +225,7 @@ namespace Icinga\Test {
 | 
				
			|||||||
        /**
 | 
					        /**
 | 
				
			||||||
         * PHPUnit provider for pgsql
 | 
					         * PHPUnit provider for pgsql
 | 
				
			||||||
         *
 | 
					         *
 | 
				
			||||||
         * @return Connection
 | 
					         * @return DbConnection
 | 
				
			||||||
         */
 | 
					         */
 | 
				
			||||||
        public function pgsqlDb()
 | 
					        public function pgsqlDb()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
@ -235,7 +235,7 @@ namespace Icinga\Test {
 | 
				
			|||||||
        /**
 | 
					        /**
 | 
				
			||||||
         * PHPUnit provider for oracle
 | 
					         * PHPUnit provider for oracle
 | 
				
			||||||
         *
 | 
					         *
 | 
				
			||||||
         * @return Connection
 | 
					         * @return DbConnection
 | 
				
			||||||
         */
 | 
					         */
 | 
				
			||||||
        public function oracleDb()
 | 
					        public function oracleDb()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
@ -245,12 +245,12 @@ namespace Icinga\Test {
 | 
				
			|||||||
        /**
 | 
					        /**
 | 
				
			||||||
         * Executes sql file by using the database connection
 | 
					         * Executes sql file by using the database connection
 | 
				
			||||||
         *
 | 
					         *
 | 
				
			||||||
         * @param   Connection      $resource
 | 
					         * @param   DbConnection      $resource
 | 
				
			||||||
         * @param   string          $filename
 | 
					         * @param   string          $filename
 | 
				
			||||||
         *
 | 
					         *
 | 
				
			||||||
         * @throws  RuntimeException
 | 
					         * @throws  RuntimeException
 | 
				
			||||||
         */
 | 
					         */
 | 
				
			||||||
        public function loadSql(Connection $resource, $filename)
 | 
					        public function loadSql(DbConnection $resource, $filename)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            if (!is_file($filename)) {
 | 
					            if (!is_file($filename)) {
 | 
				
			||||||
                throw new RuntimeException(
 | 
					                throw new RuntimeException(
 | 
				
			||||||
@ -272,11 +272,11 @@ namespace Icinga\Test {
 | 
				
			|||||||
        /**
 | 
					        /**
 | 
				
			||||||
         * Setup provider for testcase
 | 
					         * Setup provider for testcase
 | 
				
			||||||
         *
 | 
					         *
 | 
				
			||||||
         * @param   string|Connection|null $resource
 | 
					         * @param   string|DbConnection|null $resource
 | 
				
			||||||
         */
 | 
					         */
 | 
				
			||||||
        public function setupDbProvider($resource)
 | 
					        public function setupDbProvider($resource)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            if (!$resource instanceof Connection) {
 | 
					            if (!$resource instanceof DbConnection) {
 | 
				
			||||||
                if (is_string($resource)) {
 | 
					                if (is_string($resource)) {
 | 
				
			||||||
                    $this->markTestSkipped('Could not initialize provider: ' . $resource);
 | 
					                    $this->markTestSkipped('Could not initialize provider: ' . $resource);
 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
 | 
				
			|||||||
@ -29,45 +29,45 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace Icinga\Test;
 | 
					namespace Icinga\Test;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use Icinga\Data\Db\Connection;
 | 
					use Icinga\Data\Db\DbConnection;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
interface DbTest
 | 
					interface DbTest
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * PHPUnit provider for mysql
 | 
					     * PHPUnit provider for mysql
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @return Connection
 | 
					     * @return DbConnection
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public function mysqlDb();
 | 
					    public function mysqlDb();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * PHPUnit provider for pgsql
 | 
					     * PHPUnit provider for pgsql
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @return Connection
 | 
					     * @return DbConnection
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public function pgsqlDb();
 | 
					    public function pgsqlDb();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * PHPUnit provider for oracle
 | 
					     * PHPUnit provider for oracle
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @return Connection
 | 
					     * @return DbConnection
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public function oracleDb();
 | 
					    public function oracleDb();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Executes sql file on PDO object
 | 
					     * Executes sql file on PDO object
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @param   Connection      $resource
 | 
					     * @param   DbConnection      $resource
 | 
				
			||||||
     * @param   string          $filename
 | 
					     * @param   string          $filename
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @return  boolean Operational success flag
 | 
					     * @return  boolean Operational success flag
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public function loadSql(Connection $resource, $filename);
 | 
					    public function loadSql(DbConnection $resource, $filename);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Setup provider for testcase
 | 
					     * Setup provider for testcase
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @param   string|Connection|null $resource
 | 
					     * @param   string|DbConnection|null $resource
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public function setupDbProvider($resource);
 | 
					    public function setupDbProvider($resource);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -9,7 +9,7 @@ use Icinga\User;
 | 
				
			|||||||
use Icinga\User\Preferences;
 | 
					use Icinga\User\Preferences;
 | 
				
			||||||
use Icinga\Data\ResourceFactory;
 | 
					use Icinga\Data\ResourceFactory;
 | 
				
			||||||
use Icinga\Exception\ConfigurationError;
 | 
					use Icinga\Exception\ConfigurationError;
 | 
				
			||||||
use Icinga\Data\Db\Connection as DbConnection;
 | 
					use Icinga\Data\Db\DbConnection;
 | 
				
			||||||
use Icinga\Application\Config as IcingaConfig;
 | 
					use Icinga\Application\Config as IcingaConfig;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 | 
				
			|||||||
@ -154,7 +154,7 @@ class BaseTestCaseTest extends BaseTestCase
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    public function testWhetherLoadSqlThrowsErrorWhenFileMissing()
 | 
					    public function testWhetherLoadSqlThrowsErrorWhenFileMissing()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $this->loadSql(Mockery::mock('Icinga\Data\Db\Connection'), 'not_existing');
 | 
					        $this->loadSql(Mockery::mock('Icinga\Data\Db\DbConnection'), 'not_existing');
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
@ -163,7 +163,7 @@ class BaseTestCaseTest extends BaseTestCase
 | 
				
			|||||||
    public function testWhetherLoadSqlThrowsErrorWhenFileEmpty()
 | 
					    public function testWhetherLoadSqlThrowsErrorWhenFileEmpty()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $this->emptySqlDumpFile = tempnam(sys_get_temp_dir(), 'icinga2-web-db-test-empty');
 | 
					        $this->emptySqlDumpFile = tempnam(sys_get_temp_dir(), 'icinga2-web-db-test-empty');
 | 
				
			||||||
        $this->loadSql(Mockery::mock('Icinga\Data\Db\Connection'), $this->emptySqlDumpFile);
 | 
					        $this->loadSql(Mockery::mock('Icinga\Data\Db\DbConnection'), $this->emptySqlDumpFile);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected function dbAdapterSqlLoadTable($resource)
 | 
					    protected function dbAdapterSqlLoadTable($resource)
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user