mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-27 01:02:42 +01:00
Implement function-driven logical project queries in Differential
Summary: Ref T4100. Ref T5595. This implements these fields in one mega-field: - Projects - Not in projects - In any project - Include results in no projects - In users' projects Hopefully, this is a step in the right direction. Test Plan: {F375555} Reviewers: btrahan Reviewed By: btrahan Subscribers: joshuaspence, chad, epriestley Maniphest Tasks: T4100, T5595 Differential Revision: https://secure.phabricator.com/D12463
This commit is contained in:
parent
f331463d50
commit
4005bff567
9 changed files with 95 additions and 15 deletions
|
@ -596,14 +596,17 @@ final class DifferentialRevisionQuery
|
||||||
private function buildSelectStatement(AphrontDatabaseConnection $conn_r) {
|
private function buildSelectStatement(AphrontDatabaseConnection $conn_r) {
|
||||||
$table = new DifferentialRevision();
|
$table = new DifferentialRevision();
|
||||||
|
|
||||||
$select = qsprintf(
|
$select = $this->buildSelectClause($conn_r);
|
||||||
|
|
||||||
|
$from = qsprintf(
|
||||||
$conn_r,
|
$conn_r,
|
||||||
'SELECT r.* FROM %T r',
|
'FROM %T r',
|
||||||
$table->getTableName());
|
$table->getTableName());
|
||||||
|
|
||||||
$joins = $this->buildJoinsClause($conn_r);
|
$joins = $this->buildJoinsClause($conn_r);
|
||||||
$where = $this->buildWhereClause($conn_r);
|
$where = $this->buildWhereClause($conn_r);
|
||||||
$group_by = $this->buildGroupByClause($conn_r);
|
$group_by = $this->buildGroupByClause($conn_r);
|
||||||
|
$having = $this->buildHavingClause($conn_r);
|
||||||
|
|
||||||
$this->buildingGlobalOrder = false;
|
$this->buildingGlobalOrder = false;
|
||||||
$order_by = $this->buildOrderClause($conn_r);
|
$order_by = $this->buildOrderClause($conn_r);
|
||||||
|
@ -612,11 +615,13 @@ final class DifferentialRevisionQuery
|
||||||
|
|
||||||
return qsprintf(
|
return qsprintf(
|
||||||
$conn_r,
|
$conn_r,
|
||||||
'(%Q %Q %Q %Q %Q %Q)',
|
'(%Q %Q %Q %Q %Q %Q %Q %Q)',
|
||||||
$select,
|
$select,
|
||||||
|
$from,
|
||||||
$joins,
|
$joins,
|
||||||
$where,
|
$where,
|
||||||
$group_by,
|
$group_by,
|
||||||
|
$having,
|
||||||
$order_by,
|
$order_by,
|
||||||
$limit);
|
$limit);
|
||||||
}
|
}
|
||||||
|
@ -684,9 +689,9 @@ final class DifferentialRevisionQuery
|
||||||
DifferentialRevision::TABLE_COMMIT);
|
DifferentialRevision::TABLE_COMMIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
$joins = implode(' ', $joins);
|
$joins[] = $this->buildJoinClauseParts($conn_r);
|
||||||
|
|
||||||
return $joins;
|
return $this->formatJoinClause($joins);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -839,7 +844,7 @@ final class DifferentialRevisionQuery
|
||||||
"Unknown revision status filter constant '{$this->status}'!");
|
"Unknown revision status filter constant '{$this->status}'!");
|
||||||
}
|
}
|
||||||
|
|
||||||
$where[] = $this->buildPagingClause($conn_r);
|
$where[] = $this->buildWhereClauseParts($conn_r);
|
||||||
return $this->formatWhereClause($where);
|
return $this->formatWhereClause($where);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1161,4 +1166,8 @@ final class DifferentialRevisionQuery
|
||||||
return 'PhabricatorDifferentialApplication';
|
return 'PhabricatorDifferentialApplication';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function getPrimaryTableAlias() {
|
||||||
|
return 'r';
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,6 +46,11 @@ final class DifferentialRevisionSearchEngine
|
||||||
'repositoryPHIDs',
|
'repositoryPHIDs',
|
||||||
$request->getArr('repositories'));
|
$request->getArr('repositories'));
|
||||||
|
|
||||||
|
// TODO: Implement "readProjectsFromRequest(...)" to improve this.
|
||||||
|
$saved->setParameter(
|
||||||
|
'projects',
|
||||||
|
$this->readListFromRequest($request, 'projects'));
|
||||||
|
|
||||||
$saved->setParameter(
|
$saved->setParameter(
|
||||||
'draft',
|
'draft',
|
||||||
$request->getBool('draft'));
|
$request->getBool('draft'));
|
||||||
|
@ -76,6 +81,8 @@ final class DifferentialRevisionSearchEngine
|
||||||
$query->withResponsibleUsers($responsible_phids);
|
$query->withResponsibleUsers($responsible_phids);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->setQueryProjects($query, $saved);
|
||||||
|
|
||||||
$author_phids = $saved->getParameter('authorPHIDs', array());
|
$author_phids = $saved->getParameter('authorPHIDs', array());
|
||||||
if ($author_phids) {
|
if ($author_phids) {
|
||||||
$query->withAuthors($author_phids);
|
$query->withAuthors($author_phids);
|
||||||
|
@ -127,6 +134,7 @@ final class DifferentialRevisionSearchEngine
|
||||||
$subscriber_phids = $saved->getParameter('subscriberPHIDs', array());
|
$subscriber_phids = $saved->getParameter('subscriberPHIDs', array());
|
||||||
$repository_phids = $saved->getParameter('repositoryPHIDs', array());
|
$repository_phids = $saved->getParameter('repositoryPHIDs', array());
|
||||||
$only_draft = $saved->getParameter('draft', false);
|
$only_draft = $saved->getParameter('draft', false);
|
||||||
|
$projects = $saved->getParameter('projects', array());
|
||||||
|
|
||||||
$form
|
$form
|
||||||
->appendControl(
|
->appendControl(
|
||||||
|
@ -159,6 +167,12 @@ final class DifferentialRevisionSearchEngine
|
||||||
->setName('repositories')
|
->setName('repositories')
|
||||||
->setDatasource(new DiffusionRepositoryDatasource())
|
->setDatasource(new DiffusionRepositoryDatasource())
|
||||||
->setValue($repository_phids))
|
->setValue($repository_phids))
|
||||||
|
->appendControl(
|
||||||
|
id(new AphrontFormTokenizerControl())
|
||||||
|
->setLabel(pht('Projects'))
|
||||||
|
->setName('projects')
|
||||||
|
->setDatasource(new PhabricatorProjectLogicalDatasource())
|
||||||
|
->setValue($projects))
|
||||||
->appendChild(
|
->appendChild(
|
||||||
id(new AphrontFormSelectControl())
|
id(new AphrontFormSelectControl())
|
||||||
->setLabel(pht('Status'))
|
->setLabel(pht('Status'))
|
||||||
|
|
|
@ -17,13 +17,13 @@ final class PhabricatorProjectLogicalAndDatasource
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function evaluateTokens(array $tokens) {
|
protected function didEvaluateTokens(array $results) {
|
||||||
$results = parent::evaluateTokens($tokens);
|
|
||||||
|
|
||||||
foreach ($results as $key => $result) {
|
foreach ($results as $key => $result) {
|
||||||
$results[$key] = new PhabricatorQueryConstraint(
|
if (is_string($result)) {
|
||||||
PhabricatorQueryConstraint::OPERATOR_AND,
|
$results[$key] = new PhabricatorQueryConstraint(
|
||||||
$result);
|
PhabricatorQueryConstraint::OPERATOR_AND,
|
||||||
|
$result);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $results;
|
return $results;
|
||||||
|
|
|
@ -75,7 +75,7 @@ final class PhabricatorProjectLogicalOrNotDatasource
|
||||||
$phid);
|
$phid);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $phids;
|
return $results;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function renderFunctionTokens($function, array $argv_list) {
|
public function renderFunctionTokens($function, array $argv_list) {
|
||||||
|
|
|
@ -56,7 +56,7 @@ final class PhabricatorProjectLogicalViewerDatasource
|
||||||
return $results;
|
return $results;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function renderViewerProjectsFunctionTokens(
|
public function renderFunctionTokens(
|
||||||
$function,
|
$function,
|
||||||
array $argv_list) {
|
array $argv_list) {
|
||||||
|
|
||||||
|
|
|
@ -219,6 +219,23 @@ abstract class PhabricatorApplicationSearchEngine {
|
||||||
return $named_queries;
|
return $named_queries;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function setQueryProjects(
|
||||||
|
PhabricatorCursorPagedPolicyAwareQuery $query,
|
||||||
|
PhabricatorSavedQuery $saved) {
|
||||||
|
|
||||||
|
$datasource = id(new PhabricatorProjectLogicalDatasource())
|
||||||
|
->setViewer($this->requireViewer());
|
||||||
|
|
||||||
|
$projects = $saved->getParameter('projects', array());
|
||||||
|
$constraints = $datasource->evaluateTokens($projects);
|
||||||
|
|
||||||
|
if ($constraints) {
|
||||||
|
$query->withEdgeLogicConstraints(
|
||||||
|
PhabricatorProjectObjectHasProjectEdgeType::EDGECONST,
|
||||||
|
$constraints);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* -( Applications )------------------------------------------------------- */
|
/* -( Applications )------------------------------------------------------- */
|
||||||
|
|
||||||
|
|
|
@ -117,6 +117,12 @@ abstract class PhabricatorTypeaheadCompositeDatasource
|
||||||
return $this->usable;
|
return $this->usable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function didEvaluateTokens(array $results) {
|
||||||
|
foreach ($this->getUsableDatasources() as $source) {
|
||||||
|
$results = $source->didEvaluateTokens($results);
|
||||||
|
}
|
||||||
|
return $results;
|
||||||
|
}
|
||||||
|
|
||||||
protected function canEvaluateFunction($function) {
|
protected function canEvaluateFunction($function) {
|
||||||
foreach ($this->getUsableDatasources() as $source) {
|
foreach ($this->getUsableDatasources() as $source) {
|
||||||
|
|
|
@ -324,6 +324,16 @@ abstract class PhabricatorTypeaheadDatasource extends Phobject {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$results = $this->didEvaluateTokens($results);
|
||||||
|
|
||||||
|
return $results;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @task functions
|
||||||
|
*/
|
||||||
|
protected function didEvaluateTokens(array $results) {
|
||||||
return $results;
|
return $results;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ abstract class PhabricatorCursorPagedPolicyAwareQuery
|
||||||
private $internalPaging;
|
private $internalPaging;
|
||||||
private $orderVector;
|
private $orderVector;
|
||||||
private $builtinOrder;
|
private $builtinOrder;
|
||||||
|
private $edgeLogicConstraints = array();
|
||||||
|
|
||||||
protected function getPageCursors(array $page) {
|
protected function getPageCursors(array $page) {
|
||||||
return array(
|
return array(
|
||||||
|
@ -1315,6 +1316,10 @@ abstract class PhabricatorCursorPagedPolicyAwareQuery
|
||||||
|
|
||||||
$joins = array();
|
$joins = array();
|
||||||
foreach ($this->edgeLogicConstraints as $type => $constraints) {
|
foreach ($this->edgeLogicConstraints as $type => $constraints) {
|
||||||
|
|
||||||
|
$op_null = PhabricatorQueryConstraint::OPERATOR_NULL;
|
||||||
|
$has_null = isset($constraints[$op_null]);
|
||||||
|
|
||||||
foreach ($constraints as $operator => $list) {
|
foreach ($constraints as $operator => $list) {
|
||||||
$alias = $this->getEdgeLogicTableAlias($operator, $type);
|
$alias = $this->getEdgeLogicTableAlias($operator, $type);
|
||||||
switch ($operator) {
|
switch ($operator) {
|
||||||
|
@ -1334,10 +1339,20 @@ abstract class PhabricatorCursorPagedPolicyAwareQuery
|
||||||
break;
|
break;
|
||||||
case PhabricatorQueryConstraint::OPERATOR_AND:
|
case PhabricatorQueryConstraint::OPERATOR_AND:
|
||||||
case PhabricatorQueryConstraint::OPERATOR_OR:
|
case PhabricatorQueryConstraint::OPERATOR_OR:
|
||||||
|
// If we're including results with no matches, we have to degrade
|
||||||
|
// this to a LEFT join. We'll use WHERE to select matching rows
|
||||||
|
// later.
|
||||||
|
if ($has_null) {
|
||||||
|
$join_type = 'LEFT';
|
||||||
|
} else {
|
||||||
|
$join_type = '';
|
||||||
|
}
|
||||||
|
|
||||||
$joins[] = qsprintf(
|
$joins[] = qsprintf(
|
||||||
$conn,
|
$conn,
|
||||||
'JOIN %T %T ON %Q = %T.src AND %T.type = %d
|
'%Q JOIN %T %T ON %Q = %T.src AND %T.type = %d
|
||||||
AND %T.dst IN (%Ls)',
|
AND %T.dst IN (%Ls)',
|
||||||
|
$join_type,
|
||||||
$edge_table,
|
$edge_table,
|
||||||
$alias,
|
$alias,
|
||||||
$phid_column,
|
$phid_column,
|
||||||
|
@ -1377,6 +1392,9 @@ abstract class PhabricatorCursorPagedPolicyAwareQuery
|
||||||
$full = array();
|
$full = array();
|
||||||
$null = array();
|
$null = array();
|
||||||
|
|
||||||
|
$op_null = PhabricatorQueryConstraint::OPERATOR_NULL;
|
||||||
|
$has_null = isset($constraints[$op_null]);
|
||||||
|
|
||||||
foreach ($constraints as $operator => $list) {
|
foreach ($constraints as $operator => $list) {
|
||||||
$alias = $this->getEdgeLogicTableAlias($operator, $type);
|
$alias = $this->getEdgeLogicTableAlias($operator, $type);
|
||||||
switch ($operator) {
|
switch ($operator) {
|
||||||
|
@ -1388,6 +1406,12 @@ abstract class PhabricatorCursorPagedPolicyAwareQuery
|
||||||
break;
|
break;
|
||||||
case PhabricatorQueryConstraint::OPERATOR_AND:
|
case PhabricatorQueryConstraint::OPERATOR_AND:
|
||||||
case PhabricatorQueryConstraint::OPERATOR_OR:
|
case PhabricatorQueryConstraint::OPERATOR_OR:
|
||||||
|
if ($has_null) {
|
||||||
|
$full[] = qsprintf(
|
||||||
|
$conn,
|
||||||
|
'%T.dst IS NOT NULL',
|
||||||
|
$alias);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case PhabricatorQueryConstraint::OPERATOR_NULL:
|
case PhabricatorQueryConstraint::OPERATOR_NULL:
|
||||||
$null[] = qsprintf(
|
$null[] = qsprintf(
|
||||||
|
|
Loading…
Reference in a new issue