. * * */ class Staple_Query_Union { const DISTINCT = 'DISTINCT'; const ALL = 'ALL'; /** * The database object. A database object is required to properly escape input. * @var mysqli */ protected $db; /** * UNION flag: ALL | DISTINCT * @var string */ protected $flag; /** * An array of the queries to union. * @var array[Staple_Query] */ protected $queries = array(); /** * Holds the order of the SQL query. It can be either a string or an array of the columns to order by. * @var string | array */ protected $order; /** * Limit number of rows to return. * @var int */ protected $limit; /** * The Limit Offset. Used to skip a number of rows before selecting. * @var int */ protected $limitOffset; /** * Constructor accepts an array of Staple_Query_Select elements and a database connection. * @param array $queries * @param mysqli $db */ public function __construct(array $queries = array(), mysqli $db = NULL) { //Process Database connection if($db instanceof mysqli) { $this->setDb($db); } else { try { $this->setDb(Staple_DB::get()); } catch (Exception $e) { $this->setDb(new mysqli()); } } //No DB = Bad if(!($this->db instanceof mysqli)) { throw new Exception('Unable to create database object', Staple_Error::DB_ERROR); } foreach($queries as $q) { if($q instanceof Staple_Query_Select) { $this->addQuery($q); } } } /** * Builds the query on string conversion. * @return string */ public function __toString() { return $this->build(); } /** * @return mysqli $db */ public function getDb() { return $this->db; } /** * Get the UNION flag: ALL | DISTINCT */ public function getFlag() { return $this->flag; } /** * Returns the order. * @return string | array */ public function getOrder() { return $this->order; } /** * @return the $limit */ public function getLimit() { return $this->limit; } /** * @return the $limitOffset */ public function getLimitOffset() { return $this->limitOffset; } /** * @param mysqli $db */ public function setDb(mysqli $db) { $this->db = $db; return $this; } /** * Set the UNION flag. * @param string $flag */ public function setFlag($flag) { $flag = strtoupper($flag); switch($flag) { case self::ALL: case self::DISTINCT: $this->flag = $flag; } return $this; } /** * Resets all of the columns in all the currently added queries to the specified column array. */ public function setColumns(array $columns) { foreach($this->queries as $query) { $query->setColumns($columns); } return $this; } /** * Set the order. * @param string | array $order */ public function setOrder($order) { $this->order = $order; return $this; } /** * @param int $limit * @return Staple_Query_Select */ public function setLimit($limit) { $this->limit = (int)$limit; return $this; } /** * @param int $limitOffset * @return Staple_Query_Select */ public function setLimitOffset($limitOffset) { $this->limitOffset = (int)$limitOffset; return $this; } /** * Add a query to the UNION * @param Staple_Query_Select $query */ public function addQuery(Staple_Query_Select $query) { $this->queries[] = $query; return $this; } /** * Remove a query from the UNION * @param Staple_Query_Select $query */ public function removeQuery(Staple_Query_Select $query) { if(($key = array_search($query, $this->queries, true)) !== false) { unset($this->queries[$key]); } return $this; } function build() { $stmt = ''; if(count($this->queries) <= 0) { return 'SELECT 0 FROM (SELECT 0) AS `a` WHERE 1=0'; } elseif(count($this->queries) == 1) { $stmt .= 'SELECT * FROM ('.implode('', $this->queries).') AS `stapleunion` '; } else { if(isset($this->flag)) { $glue = ")\nUNION {$this->flag} \n("; } else { $glue = ")\nUNION \n("; } $stmt .= '('.implode($glue, $this->queries).')'; } //ORDER CLAUSE if(isset($this->order)) { $stmt .= "\nORDER BY "; if(is_array($this->order)) { $stmt .= implode(',', $this->order); } else { $stmt .= $this->order; } } //LIMIT CLAUSE if(isset($this->limit)) { $stmt .= "\nLIMIT ".$this->getLimit(); if(isset($this->limitOffset)) { $stmt .= ' OFFSET '.$this->limitOffset; } } return $stmt; } /** * Alias of setOrder() * @see self::setOrder() */ public function orderBy($order) { return $this->setOrder($order); } /** * Sets the limit and the offset in one function. * @param int | Staple_Pager $limit * @param int $offset */ public function limit($limit,$offset = NULL) { if($limit instanceof Staple_Pager) { $this->setLimit($limit->getItemsPerPage()); $this->setLimitOffset($limit->getStartingItem()); } else { $this->setLimit($limit); if(isset($offset)) $this->setLimitOffset($offset); } return $this; } /** * Executes the query. * @return mysqli_result | bool */ public function Execute() { if($this->db instanceof mysqli) { return $this->db->query($this->build()); } else { try { $this->db = Staple_DB::get(); } catch (Exception $e) { //@todo try for a default connection if no staple connection throw new Exception('No Database Connection', Staple_Error::DB_ERROR); } if($this->db instanceof mysqli) { return $this->db->query($this->build()); } } return false; } } ?>