* @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 * @author Icinga Development Team * */ // {{{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; } }