1
0
Fork 0
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:
epriestley 2015-04-18 11:18:27 -07:00
parent f331463d50
commit 4005bff567
9 changed files with 95 additions and 15 deletions

View file

@ -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';
}
} }

View file

@ -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'))

View file

@ -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;

View file

@ -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) {

View file

@ -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) {

View file

@ -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 )------------------------------------------------------- */

View file

@ -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) {

View file

@ -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;
} }

View file

@ -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(