diff --git a/src/applications/almanac/query/AlmanacServiceQuery.php b/src/applications/almanac/query/AlmanacServiceQuery.php --- a/src/applications/almanac/query/AlmanacServiceQuery.php +++ b/src/applications/almanac/query/AlmanacServiceQuery.php @@ -75,7 +75,7 @@ return $table->loadAllFromArray($data); } - protected function buildJoinClause($conn_r) { + protected function buildJoinClause(AphrontDatabaseConnection $conn_r) { $joins = array(); if ($this->devicePHIDs !== null) { diff --git a/src/applications/conpherence/query/ConpherenceThreadQuery.php b/src/applications/conpherence/query/ConpherenceThreadQuery.php --- a/src/applications/conpherence/query/ConpherenceThreadQuery.php +++ b/src/applications/conpherence/query/ConpherenceThreadQuery.php @@ -129,7 +129,7 @@ } } - private function buildJoinClause($conn_r) { + protected function buildJoinClause(AphrontDatabaseConnection $conn_r) { $joins = array(); if ($this->participantPHIDs !== null) { diff --git a/src/applications/diffusion/query/DiffusionCommitQuery.php b/src/applications/diffusion/query/DiffusionCommitQuery.php --- a/src/applications/diffusion/query/DiffusionCommitQuery.php +++ b/src/applications/diffusion/query/DiffusionCommitQuery.php @@ -511,7 +511,7 @@ } } - private function buildJoinClause($conn_r) { + protected function buildJoinClause(AphrontDatabaseConnection $conn_r) { $joins = array(); $audit_request = new PhabricatorRepositoryAuditRequest(); diff --git a/src/applications/feed/query/PhabricatorFeedQuery.php b/src/applications/feed/query/PhabricatorFeedQuery.php --- a/src/applications/feed/query/PhabricatorFeedQuery.php +++ b/src/applications/feed/query/PhabricatorFeedQuery.php @@ -37,7 +37,7 @@ return PhabricatorFeedStory::loadAllFromRows($data, $this->getViewer()); } - private function buildJoinClause(AphrontDatabaseConnection $conn_r) { + protected function buildJoinClause(AphrontDatabaseConnection $conn_r) { // NOTE: We perform this join unconditionally (even if we have no filter // PHIDs) to omit rows which have no story references. These story data // rows are notifications or realtime alerts. diff --git a/src/applications/files/query/PhabricatorFileQuery.php b/src/applications/files/query/PhabricatorFileQuery.php --- a/src/applications/files/query/PhabricatorFileQuery.php +++ b/src/applications/files/query/PhabricatorFileQuery.php @@ -215,7 +215,7 @@ return $files; } - private function buildJoinClause(AphrontDatabaseConnection $conn_r) { + protected function buildJoinClause(AphrontDatabaseConnection $conn_r) { $joins = array(); if ($this->transforms) { diff --git a/src/applications/legalpad/query/LegalpadDocumentQuery.php b/src/applications/legalpad/query/LegalpadDocumentQuery.php --- a/src/applications/legalpad/query/LegalpadDocumentQuery.php +++ b/src/applications/legalpad/query/LegalpadDocumentQuery.php @@ -134,7 +134,7 @@ return $documents; } - private function buildJoinClause($conn_r) { + protected function buildJoinClause(AphrontDatabaseConnection $conn_r) { $joins = array(); if ($this->contributorPHIDs !== null) { diff --git a/src/applications/owners/query/PhabricatorOwnersPackageQuery.php b/src/applications/owners/query/PhabricatorOwnersPackageQuery.php --- a/src/applications/owners/query/PhabricatorOwnersPackageQuery.php +++ b/src/applications/owners/query/PhabricatorOwnersPackageQuery.php @@ -35,7 +35,7 @@ return $table->loadAllFromArray($data); } - private function buildJoinClause(AphrontDatabaseConnection $conn_r) { + protected function buildJoinClause(AphrontDatabaseConnection $conn_r) { $joins = array(); if ($this->ownerPHIDs) { diff --git a/src/applications/phortune/query/PhortuneAccountQuery.php b/src/applications/phortune/query/PhortuneAccountQuery.php --- a/src/applications/phortune/query/PhortuneAccountQuery.php +++ b/src/applications/phortune/query/PhortuneAccountQuery.php @@ -102,7 +102,7 @@ return $this->formatWhereClause($where); } - private function buildJoinClause(AphrontDatabaseConnection $conn) { + protected function buildJoinClause(AphrontDatabaseConnection $conn) { $joins = array(); if ($this->memberPHIDs) { diff --git a/src/applications/phortune/query/PhortuneMerchantQuery.php b/src/applications/phortune/query/PhortuneMerchantQuery.php --- a/src/applications/phortune/query/PhortuneMerchantQuery.php +++ b/src/applications/phortune/query/PhortuneMerchantQuery.php @@ -82,7 +82,7 @@ return $this->formatWhereClause($where); } - private function buildJoinClause(AphrontDatabaseConnection $conn) { + protected function buildJoinClause(AphrontDatabaseConnection $conn) { $joins = array(); if ($this->memberPHIDs !== null) { diff --git a/src/applications/phriction/query/PhrictionDocumentQuery.php b/src/applications/phriction/query/PhrictionDocumentQuery.php --- a/src/applications/phriction/query/PhrictionDocumentQuery.php +++ b/src/applications/phriction/query/PhrictionDocumentQuery.php @@ -190,7 +190,7 @@ return $documents; } - private function buildJoinClause(AphrontDatabaseConnection $conn) { + protected function buildJoinClause(AphrontDatabaseConnection $conn) { $join = ''; if ($this->getOrderVector()->containsKey('updated')) { diff --git a/src/applications/project/query/PhabricatorProjectQuery.php b/src/applications/project/query/PhabricatorProjectQuery.php --- a/src/applications/project/query/PhabricatorProjectQuery.php +++ b/src/applications/project/query/PhabricatorProjectQuery.php @@ -336,7 +336,7 @@ } } - private function buildJoinClause($conn_r) { + protected function buildJoinClause(AphrontDatabaseConnection $conn_r) { $joins = array(); if (!$this->needMembers !== null) { diff --git a/src/infrastructure/daemon/workers/query/PhabricatorWorkerTriggerQuery.php b/src/infrastructure/daemon/workers/query/PhabricatorWorkerTriggerQuery.php --- a/src/infrastructure/daemon/workers/query/PhabricatorWorkerTriggerQuery.php +++ b/src/infrastructure/daemon/workers/query/PhabricatorWorkerTriggerQuery.php @@ -145,7 +145,7 @@ return $triggers; } - private function buildJoinClause(AphrontDatabaseConnection $conn_r) { + protected function buildJoinClause(AphrontDatabaseConnection $conn_r) { $joins = array(); if (($this->nextEpochMin !== null) || diff --git a/src/infrastructure/query/PhabricatorQuery.php b/src/infrastructure/query/PhabricatorQuery.php --- a/src/infrastructure/query/PhabricatorQuery.php +++ b/src/infrastructure/query/PhabricatorQuery.php @@ -1,17 +1,122 @@ flattenSubclause($parts); + if (!$parts) { + return ''; + } + + return 'WHERE '.$this->formatWhereSubclause($parts); + } + + + /** + * @task format + */ + protected function formatWhereSubclause(array $parts) { + $parts = $this->flattenSubclause($parts); + if (!$parts) { + return null; + } + + return '('.implode(') AND (', $parts).')'; + } + + + /** + * @task format + */ + protected function formatSelectClause(array $parts) { + $parts = $this->flattenSubclause($parts); + if (!$parts) { + throw new Exception(pht('Can not build empty select clause!')); + } + + return 'SELECT '.$this->formatSelectSubclause($parts); + } + + + /** + * @task format + */ + protected function formatSelectSubclause(array $parts) { + $parts = $this->flattenSubclause($parts); + if (!$parts) { + return null; + } + return implode(', ', $parts); + } + + + /** + * @task format + */ + protected function formatJoinClause(array $parts) { + $parts = $this->flattenSubclause($parts); + if (!$parts) { + return ''; + } + + return implode(' ', $parts); + } + + + /** + * @task format + */ + protected function formatHavingClause(array $parts) { + $parts = $this->flattenSubclause($parts); if (!$parts) { return ''; } - return 'WHERE ('.implode(') AND (', $parts).')'; + return 'HAVING '.$this->formatHavingSubclause($parts); + } + + + /** + * @task format + */ + protected function formatHavingSubclause(array $parts) { + $parts = $this->flattenSubclause($parts); + if (!$parts) { + return null; + } + + return '('.implode(') AND (', $parts).')'; + } + + + /** + * @task format + */ + private function flattenSubclause(array $parts) { + $result = array(); + foreach ($parts as $part) { + if (is_array($part)) { + foreach ($this->flattenSubclause($part) as $subpart) { + $result[] = $subpart; + } + } else if (strlen($part)) { + $result[] = $part; + } + } + return $result; } } diff --git a/src/infrastructure/query/policy/PhabricatorCursorPagedPolicyAwareQuery.php b/src/infrastructure/query/policy/PhabricatorCursorPagedPolicyAwareQuery.php --- a/src/infrastructure/query/policy/PhabricatorCursorPagedPolicyAwareQuery.php +++ b/src/infrastructure/query/policy/PhabricatorCursorPagedPolicyAwareQuery.php @@ -183,8 +183,81 @@ /** * @task clauses */ + protected function buildSelectClause(AphrontDatabaseConnection $conn) { + $parts = $this->buildSelectClauseParts($conn); + return $this->formatSelectClause($parts); + } + + + /** + * @task clauses + */ + protected function buildSelectClauseParts(AphrontDatabaseConnection $conn) { + $select = array(); + + $alias = $this->getPrimaryTableAlias(); + if ($alias) { + $select[] = qsprintf($conn, '%T.*', $alias); + } else { + $select[] = '*'; + } + + return $select; + } + + + /** + * @task clauses + */ + protected function buildJoinClause(AphrontDatabaseConnection $conn) { + $joins = $this->buildJoinClauseParts($conn); + return $this->formatJoinClause($joins); + } + + + /** + * @task clauses + */ + protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) { + $joins = array(); + return $joins; + } + + + /** + * @task clauses + */ protected function buildWhereClause(AphrontDatabaseConnection $conn) { - throw new PhutilMethodNotImplementedException(); + $where = $this->buildWhereClauseParts($conn); + return $this->formatWhereClause($where); + } + + + /** + * @task clauses + */ + protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) { + $where = array(); + $where[] = $this->buildPagingClause($conn); + return $where; + } + + + /** + * @task clauses + */ + protected function buildHavingClause(AphrontDatabaseConnection $conn) { + $having = $this->buildHavingClauseParts($conn); + return $this->formatHavingClause($having); + } + + + /** + * @task clauses + */ + protected function buildHavingClauseParts(AphrontDatabaseConnection $conn) { + $having = array(); + return $having; }