diff --git a/include/class.client.php b/include/class.client.php index 4cb9fc1f9bf274972497322a6d750bc1ff70e81d..886c893424c0ca09540325ccb913fdba86026673 100644 --- a/include/class.client.php +++ b/include/class.client.php @@ -294,9 +294,15 @@ class EndUser extends BaseAuthenticatedUser { // Share tickets among the organization for owners only $mine = clone $basic; - $mine->filter(Q::any(array( + $collab = clone $basic; + $mine->filter(array( 'user_id' => $this->getId(), - 'thread__collaborators__user_id' => $this->getId() + )); + + // TODO: Implement UNION ALL support in the ORM + $mine->union($collab->filter(array( + 'thread__collaborators__user_id' => $this->getId(), + Q::not(array('user_id' => $this->getId())) ))); if ($this->getOrgId()) { @@ -305,8 +311,6 @@ class EndUser extends BaseAuthenticatedUser { ->values('user__org_id'); } - // TODO: Implement UNION ALL support in the ORM - return array('mine' => $mine, 'myorg' => $myorg); } diff --git a/include/class.orm.php b/include/class.orm.php index 9714a58c6b5e6b6894db3ce8d059be87c45d5a5b..f31e209d0bc0791e2250170a77759bc8b641c3e8 100644 --- a/include/class.orm.php +++ b/include/class.orm.php @@ -913,6 +913,7 @@ class QuerySet implements IteratorAggregate, ArrayAccess, Serializable, Countabl var $extra = array(); var $distinct = array(); var $lock = false; + var $chain = array(); const LOCK_EXCLUSIVE = 1; const LOCK_SHARED = 2; @@ -1174,6 +1175,17 @@ class QuerySet implements IteratorAggregate, ArrayAccess, Serializable, Countabl return $this; } + function union(QuerySet $other, $all=true) { + // Values and values_list _must_ match for this to work + if (count($this->values) != count($other->values)) + throw new OrmException('Union queries must have matching values counts'); + + // TODO: Clear OFFSET and LIMIT in the $other query + + $this->chain[] = array($other, $all); + return $this; + } + function delete() { $class = $this->compiler; $compiler = new $class(); @@ -2529,8 +2541,26 @@ class MySqlCompiler extends SqlCompiler { $joins = $this->getJoins($queryset); + // UNIONS + $unions=''; + if ($queryset->chain) { + foreach ($queryset->chain as $qs) { + list($qs, $all) = $qs; + $q = $qs->getQuery(array('nosort' => true)); + // Rewrite the parameter numbers so they fit the parameter numbers + // of the current parameters of the $compiler + $self = $this; + $sql = preg_replace_callback("/:(\d+)/", + function($m) use ($self, $q) { + $self->params[] = $q->params[$m[1]-1]; + return ':'.count($self->params); + }, $q->sql); + $unions .= ' UNION '.($all ? 'ALL ' : '').$sql; + } + } + $sql = 'SELECT '.implode(', ', $fields).' FROM ' - .$table.$joins.$where.$group_by.$having.$sort; + .$table.$joins.$where.$group_by.$having.$unions.$sort; if ($queryset->limit) $sql .= ' LIMIT '.$queryset->limit; if ($queryset->offset)