Changeset View
Changeset View
Standalone View
Standalone View
src/applications/differential/query/DifferentialRevisionQuery.php
Show All 27 Lines | final class DifferentialRevisionQuery | ||||
private $authors = array(); | private $authors = array(); | ||||
private $draftAuthors = array(); | private $draftAuthors = array(); | ||||
private $ccs = array(); | private $ccs = array(); | ||||
private $reviewers = array(); | private $reviewers = array(); | ||||
private $revIDs = array(); | private $revIDs = array(); | ||||
private $commitHashes = array(); | private $commitHashes = array(); | ||||
private $phids = array(); | private $phids = array(); | ||||
private $subscribers = array(); | |||||
private $responsibles = array(); | private $responsibles = array(); | ||||
private $branches = array(); | private $branches = array(); | ||||
private $arcanistProjectPHIDs = array(); | private $arcanistProjectPHIDs = array(); | ||||
private $draftRevisions = array(); | private $draftRevisions = array(); | ||||
private $repositoryPHIDs; | private $repositoryPHIDs; | ||||
private $order = 'order-modified'; | private $order = 'order-modified'; | ||||
const ORDER_MODIFIED = 'order-modified'; | const ORDER_MODIFIED = 'order-modified'; | ||||
▲ Show 20 Lines • Show All 64 Lines • ▼ Show 20 Lines | public function withDraftRepliesByAuthors(array $author_phids) { | ||||
$this->draftAuthors = $author_phids; | $this->draftAuthors = $author_phids; | ||||
return $this; | return $this; | ||||
} | } | ||||
/** | /** | ||||
* Filter results to revisions which CC one of the listed people. Calling this | * Filter results to revisions which CC one of the listed people. Calling this | ||||
* function will clear anything set by previous calls to @{method:withCCs}. | * function will clear anything set by previous calls to @{method:withCCs}. | ||||
* | * | ||||
* @param array List of PHIDs of subscribers | * @param array List of PHIDs of subscribers. | ||||
* @return this | * @return this | ||||
* @task config | * @task config | ||||
*/ | */ | ||||
public function withCCs(array $cc_phids) { | public function withCCs(array $cc_phids) { | ||||
$this->ccs = $cc_phids; | $this->ccs = $cc_phids; | ||||
return $this; | return $this; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 90 Lines • ▼ Show 20 Lines | /* -( Query Configuration )------------------------------------------------ */ | ||||
*/ | */ | ||||
public function withResponsibleUsers(array $responsible_phids) { | public function withResponsibleUsers(array $responsible_phids) { | ||||
$this->responsibles = $responsible_phids; | $this->responsibles = $responsible_phids; | ||||
return $this; | return $this; | ||||
} | } | ||||
/** | /** | ||||
* Filter results to only return revisions with a given set of subscribers | |||||
* (i.e., they are authors, reviewers or CC'd). | |||||
* | |||||
* @param array List of user PHIDs. | |||||
* @return this | |||||
* @task config | |||||
*/ | |||||
public function withSubscribers(array $subscriber_phids) { | |||||
$this->subscribers = $subscriber_phids; | |||||
return $this; | |||||
} | |||||
/** | |||||
* Filter results to only return revisions with a given set of arcanist | * Filter results to only return revisions with a given set of arcanist | ||||
* projects. | * projects. | ||||
* | * | ||||
* @param array List of project PHIDs. | * @param array List of project PHIDs. | ||||
* @return this | * @return this | ||||
* @task config | * @task config | ||||
*/ | */ | ||||
public function withArcanistProjectPHIDs(array $arc_project_phids) { | public function withArcanistProjectPHIDs(array $arc_project_phids) { | ||||
▲ Show 20 Lines • Show All 377 Lines • ▼ Show 20 Lines | if ($this->commitHashes) { | ||||
$conn_r, | $conn_r, | ||||
'JOIN %T hash_rel ON hash_rel.revisionID = r.id', | 'JOIN %T hash_rel ON hash_rel.revisionID = r.id', | ||||
ArcanistDifferentialRevisionHash::TABLE_NAME); | ArcanistDifferentialRevisionHash::TABLE_NAME); | ||||
} | } | ||||
if ($this->ccs) { | if ($this->ccs) { | ||||
$joins[] = qsprintf( | $joins[] = qsprintf( | ||||
$conn_r, | $conn_r, | ||||
'JOIN %T cc_rel ON cc_rel.revisionID = r.id '. | 'JOIN %T e_ccs ON e_ccs.src = r.phid '. | ||||
'AND cc_rel.relation = %s '. | 'AND e_ccs.type = %s '. | ||||
'AND cc_rel.objectPHID in (%Ls)', | 'AND e_ccs.dst in (%Ls)', | ||||
DifferentialRevision::RELATIONSHIP_TABLE, | PhabricatorEdgeConfig::TABLE_NAME_EDGE, | ||||
DifferentialRevision::RELATION_SUBSCRIBED, | PhabricatorEdgeConfig::TYPE_OBJECT_HAS_SUBSCRIBER, | ||||
$this->ccs); | $this->ccs); | ||||
} | } | ||||
if ($this->reviewers) { | if ($this->reviewers) { | ||||
$joins[] = qsprintf( | $joins[] = qsprintf( | ||||
$conn_r, | $conn_r, | ||||
'JOIN %T e_reviewers ON e_reviewers.src = r.phid '. | 'JOIN %T e_reviewers ON e_reviewers.src = r.phid '. | ||||
'AND e_reviewers.type = %s '. | 'AND e_reviewers.type = %s '. | ||||
'AND e_reviewers.dst in (%Ls)', | 'AND e_reviewers.dst in (%Ls)', | ||||
PhabricatorEdgeConfig::TABLE_NAME_EDGE, | PhabricatorEdgeConfig::TABLE_NAME_EDGE, | ||||
PhabricatorEdgeConfig::TYPE_DREV_HAS_REVIEWER, | PhabricatorEdgeConfig::TYPE_DREV_HAS_REVIEWER, | ||||
$this->reviewers); | $this->reviewers); | ||||
} | } | ||||
if ($this->subscribers) { | |||||
// TODO: These can be expressed as a JOIN again (and the corresponding | |||||
// WHERE clause removed) once subscribers move to edges. | |||||
$joins[] = qsprintf( | |||||
$conn_r, | |||||
'LEFT JOIN %T sub_rel_cc ON sub_rel_cc.revisionID = r.id '. | |||||
'AND sub_rel_cc.relation = %s '. | |||||
'AND sub_rel_cc.objectPHID in (%Ls)', | |||||
DifferentialRevision::RELATIONSHIP_TABLE, | |||||
DifferentialRevision::RELATION_SUBSCRIBED, | |||||
$this->subscribers); | |||||
$joins[] = qsprintf( | |||||
$conn_r, | |||||
'LEFT JOIN %T sub_rel_reviewer ON sub_rel_reviewer.src = r.phid '. | |||||
'AND sub_rel_reviewer.type = %s '. | |||||
'AND sub_rel_reviewer.dst in (%Ls)', | |||||
PhabricatorEdgeConfig::TABLE_NAME_EDGE, | |||||
PhabricatorEdgeConfig::TYPE_DREV_HAS_REVIEWER, | |||||
$this->subscribers); | |||||
} | |||||
$joins = implode(' ', $joins); | $joins = implode(' ', $joins); | ||||
return $joins; | return $joins; | ||||
} | } | ||||
/** | /** | ||||
* @task internal | * @task internal | ||||
▲ Show 20 Lines • Show All 73 Lines • ▼ Show 20 Lines | private function buildWhereClause($conn_r) { | ||||
if ($this->arcanistProjectPHIDs) { | if ($this->arcanistProjectPHIDs) { | ||||
$where[] = qsprintf( | $where[] = qsprintf( | ||||
$conn_r, | $conn_r, | ||||
'r.arcanistProjectPHID in (%Ls)', | 'r.arcanistProjectPHID in (%Ls)', | ||||
$this->arcanistProjectPHIDs); | $this->arcanistProjectPHIDs); | ||||
} | } | ||||
if ($this->subscribers) { | |||||
$where[] = qsprintf( | |||||
$conn_r, | |||||
'(sub_rel_cc.objectPHID IS NOT NULL) | |||||
OR (sub_rel_reviewer.dst IS NOT NULL)'); | |||||
} | |||||
switch ($this->status) { | switch ($this->status) { | ||||
case self::STATUS_ANY: | case self::STATUS_ANY: | ||||
break; | break; | ||||
case self::STATUS_OPEN: | case self::STATUS_OPEN: | ||||
$where[] = qsprintf( | $where[] = qsprintf( | ||||
$conn_r, | $conn_r, | ||||
'r.status IN (%Ld)', | 'r.status IN (%Ld)', | ||||
DifferentialRevisionStatus::getOpenStatuses()); | DifferentialRevisionStatus::getOpenStatuses()); | ||||
▲ Show 20 Lines • Show All 48 Lines • ▼ Show 20 Lines | /* -( Internals )---------------------------------------------------------- */ | ||||
/** | /** | ||||
* @task internal | * @task internal | ||||
*/ | */ | ||||
private function buildGroupByClause($conn_r) { | private function buildGroupByClause($conn_r) { | ||||
$join_triggers = array_merge( | $join_triggers = array_merge( | ||||
$this->pathIDs, | $this->pathIDs, | ||||
$this->ccs, | $this->ccs, | ||||
$this->reviewers, | $this->reviewers); | ||||
$this->subscribers); | |||||
$needs_distinct = (count($join_triggers) > 1); | $needs_distinct = (count($join_triggers) > 1); | ||||
if ($needs_distinct) { | if ($needs_distinct) { | ||||
return 'GROUP BY r.id'; | return 'GROUP BY r.id'; | ||||
} else { | } else { | ||||
return ''; | return ''; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 83 Lines • ▼ Show 20 Lines | switch ($this->order) { | ||||
return 'p.epoch'; | return 'p.epoch'; | ||||
default: | default: | ||||
throw new Exception("Unknown query order constant '{$this->order}'."); | throw new Exception("Unknown query order constant '{$this->order}'."); | ||||
} | } | ||||
} | } | ||||
private function loadRelationships($conn_r, array $revisions) { | private function loadRelationships($conn_r, array $revisions) { | ||||
assert_instances_of($revisions, 'DifferentialRevision'); | assert_instances_of($revisions, 'DifferentialRevision'); | ||||
$relationships = queryfx_all( | |||||
$conn_r, | |||||
'SELECT * FROM %T WHERE revisionID in (%Ld) | |||||
AND relation != %s ORDER BY sequence', | |||||
DifferentialRevision::RELATIONSHIP_TABLE, | |||||
mpull($revisions, 'getID'), | |||||
DifferentialRevision::RELATION_REVIEWER); | |||||
$relationships = igroup($relationships, 'revisionID'); | |||||
$type_reviewer = PhabricatorEdgeConfig::TYPE_DREV_HAS_REVIEWER; | $type_reviewer = PhabricatorEdgeConfig::TYPE_DREV_HAS_REVIEWER; | ||||
$type_subscriber = PhabricatorEdgeConfig::TYPE_OBJECT_HAS_SUBSCRIBER; | |||||
$edges = id(new PhabricatorEdgeQuery()) | $edges = id(new PhabricatorEdgeQuery()) | ||||
->withSourcePHIDs(mpull($revisions, 'getPHID')) | ->withSourcePHIDs(mpull($revisions, 'getPHID')) | ||||
->withEdgeTypes(array($type_reviewer)) | ->withEdgeTypes(array($type_reviewer, $type_subscriber)) | ||||
->setOrder(PhabricatorEdgeQuery::ORDER_OLDEST_FIRST) | ->setOrder(PhabricatorEdgeQuery::ORDER_OLDEST_FIRST) | ||||
->execute(); | ->execute(); | ||||
$type_map = array( | |||||
DifferentialRevision::RELATION_REVIEWER => $type_reviewer, | |||||
DifferentialRevision::RELATION_SUBSCRIBED => $type_subscriber, | |||||
); | |||||
foreach ($revisions as $revision) { | foreach ($revisions as $revision) { | ||||
$data = idx($relationships, $revision->getID(), array()); | $data = array(); | ||||
$revision_edges = $edges[$revision->getPHID()][$type_reviewer]; | foreach ($type_map as $rel_type => $edge_type) { | ||||
$revision_edges = $edges[$revision->getPHID()][$edge_type]; | |||||
foreach ($revision_edges as $dst_phid => $edge_data) { | foreach ($revision_edges as $dst_phid => $edge_data) { | ||||
$data[] = array( | $data[] = array( | ||||
'relation' => DifferentialRevision::RELATION_REVIEWER, | 'relation' => $rel_type, | ||||
'objectPHID' => $dst_phid, | 'objectPHID' => $dst_phid, | ||||
'reasonPHID' => null, | 'reasonPHID' => null, | ||||
); | ); | ||||
} | } | ||||
} | |||||
$revision->attachRelationships($data); | $revision->attachRelationships($data); | ||||
} | } | ||||
} | } | ||||
private function loadCommitPHIDs($conn_r, array $revisions) { | private function loadCommitPHIDs($conn_r, array $revisions) { | ||||
assert_instances_of($revisions, 'DifferentialRevision'); | assert_instances_of($revisions, 'DifferentialRevision'); | ||||
$commit_phids = queryfx_all( | $commit_phids = queryfx_all( | ||||
▲ Show 20 Lines • Show All 225 Lines • Show Last 20 Lines |