mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-13 18:32:41 +01:00
6cc196a2e5
Summary: - `kill_init.php` said "Moving 1000 files" - I hope that this is not some limit in `FileFinder`. - [src/infrastructure/celerity] `git mv utils.php map.php; git mv api/utils.php api.php` - Comment `phutil_libraries` in `.arcconfig` and run `arc liberate`. NOTE: `arc diff` timed out so I'm pushing it without review. Test Plan: /D1234 Browsed around, especially in `applications/repository/worker/commitchangeparser` and `applications/` in general. Auditors: epriestley Maniphest Tasks: T1103
347 lines
8.8 KiB
PHP
347 lines
8.8 KiB
PHP
<?php
|
|
|
|
/*
|
|
* Copyright 2012 Facebook, Inc.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
/**
|
|
* @group search
|
|
*/
|
|
final class PhabricatorSearchEngineMySQL extends PhabricatorSearchEngine {
|
|
|
|
public function reindexAbstractDocument(
|
|
PhabricatorSearchAbstractDocument $doc) {
|
|
|
|
$phid = $doc->getPHID();
|
|
if (!$phid) {
|
|
throw new Exception("Document has no PHID!");
|
|
}
|
|
|
|
$store = new PhabricatorSearchDocument();
|
|
$store->setPHID($doc->getPHID());
|
|
$store->setDocumentType($doc->getDocumentType());
|
|
$store->setDocumentTitle($doc->getDocumentTitle());
|
|
$store->setDocumentCreated($doc->getDocumentCreated());
|
|
$store->setDocumentModified($doc->getDocumentModified());
|
|
$store->replace();
|
|
|
|
$conn_w = $store->establishConnection('w');
|
|
|
|
$field_dao = new PhabricatorSearchDocumentField();
|
|
queryfx(
|
|
$conn_w,
|
|
'DELETE FROM %T WHERE phid = %s',
|
|
$field_dao->getTableName(),
|
|
$phid);
|
|
foreach ($doc->getFieldData() as $field) {
|
|
list($ftype, $corpus, $aux_phid) = $field;
|
|
queryfx(
|
|
$conn_w,
|
|
'INSERT INTO %T (phid, phidType, field, auxPHID, corpus) '.
|
|
' VALUES (%s, %s, %s, %ns, %s)',
|
|
$field_dao->getTableName(),
|
|
$phid,
|
|
$doc->getDocumentType(),
|
|
$ftype,
|
|
$aux_phid,
|
|
$corpus);
|
|
}
|
|
|
|
|
|
$sql = array();
|
|
foreach ($doc->getRelationshipData() as $relationship) {
|
|
list($rtype, $to_phid, $to_type, $time) = $relationship;
|
|
$sql[] = qsprintf(
|
|
$conn_w,
|
|
'(%s, %s, %s, %s, %d)',
|
|
$phid,
|
|
$to_phid,
|
|
$rtype,
|
|
$to_type,
|
|
$time);
|
|
}
|
|
|
|
$rship_dao = new PhabricatorSearchDocumentRelationship();
|
|
queryfx(
|
|
$conn_w,
|
|
'DELETE FROM %T WHERE phid = %s',
|
|
$rship_dao->getTableName(),
|
|
$phid);
|
|
if ($sql) {
|
|
queryfx(
|
|
$conn_w,
|
|
'INSERT INTO %T'.
|
|
' (phid, relatedPHID, relation, relatedType, relatedTime) '.
|
|
' VALUES %Q',
|
|
$rship_dao->getTableName(),
|
|
implode(', ', $sql));
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* Rebuild the PhabricatorSearchAbstractDocument that was used to index
|
|
* an object out of the index itself. This is primarily useful for debugging,
|
|
* as it allows you to inspect the search index representation of a
|
|
* document.
|
|
*
|
|
* @param phid PHID of a document which exists in the search index.
|
|
* @return null|PhabricatorSearchAbstractDocument Abstract document object
|
|
* which corresponds to the original abstract document used to
|
|
* build the document index.
|
|
*/
|
|
public function reconstructDocument($phid) {
|
|
$dao_doc = new PhabricatorSearchDocument();
|
|
$dao_field = new PhabricatorSearchDocumentField();
|
|
$dao_relationship = new PhabricatorSearchDocumentRelationship();
|
|
|
|
$t_doc = $dao_doc->getTableName();
|
|
$t_field = $dao_field->getTableName();
|
|
$t_relationship = $dao_relationship->getTableName();
|
|
|
|
$doc = queryfx_one(
|
|
$dao_doc->establishConnection('r'),
|
|
'SELECT * FROM %T WHERE phid = %s',
|
|
$t_doc,
|
|
$phid);
|
|
|
|
if (!$doc) {
|
|
return null;
|
|
}
|
|
|
|
$fields = queryfx_all(
|
|
$dao_field->establishConnection('r'),
|
|
'SELECT * FROM %T WHERE phid = %s',
|
|
$t_field,
|
|
$phid);
|
|
|
|
$relationships = queryfx_all(
|
|
$dao_relationship->establishConnection('r'),
|
|
'SELECT * FROM %T WHERE phid = %s',
|
|
$t_relationship,
|
|
$phid);
|
|
|
|
$adoc = id(new PhabricatorSearchAbstractDocument())
|
|
->setPHID($phid)
|
|
->setDocumentType($doc['documentType'])
|
|
->setDocumentTitle($doc['documentTitle'])
|
|
->setDocumentCreated($doc['documentCreated'])
|
|
->setDocumentModified($doc['documentModified']);
|
|
|
|
foreach ($fields as $field) {
|
|
$adoc->addField(
|
|
$field['field'],
|
|
$field['corpus'],
|
|
$field['auxPHID']);
|
|
}
|
|
|
|
foreach ($relationships as $relationship) {
|
|
$adoc->addRelationship(
|
|
$relationship['relation'],
|
|
$relationship['relatedPHID'],
|
|
$relationship['relatedType'],
|
|
$relationship['relatedTime']);
|
|
}
|
|
|
|
return $adoc;
|
|
}
|
|
|
|
public function executeSearch(PhabricatorSearchQuery $query) {
|
|
|
|
$where = array();
|
|
$join = array();
|
|
$order = 'ORDER BY documentCreated DESC';
|
|
|
|
$dao_doc = new PhabricatorSearchDocument();
|
|
$dao_field = new PhabricatorSearchDocumentField();
|
|
|
|
$t_doc = $dao_doc->getTableName();
|
|
$t_field = $dao_field->getTableName();
|
|
|
|
$conn_r = $dao_doc->establishConnection('r');
|
|
|
|
$q = $query->getQuery();
|
|
|
|
if (strlen($q)) {
|
|
$join[] = qsprintf(
|
|
$conn_r,
|
|
"{$t_field} field ON field.phid = document.phid");
|
|
$where[] = qsprintf(
|
|
$conn_r,
|
|
'MATCH(corpus) AGAINST (%s IN BOOLEAN MODE)',
|
|
$q);
|
|
|
|
// When searching for a string, promote user listings above other
|
|
// listings.
|
|
$order = qsprintf(
|
|
$conn_r,
|
|
'ORDER BY
|
|
IF(documentType = %s, 0, 1) ASC,
|
|
MAX(MATCH(corpus) AGAINST (%s)) DESC',
|
|
'USER',
|
|
$q);
|
|
|
|
$field = $query->getParameter('field');
|
|
if ($field/* && $field != AdjutantQuery::FIELD_ALL*/) {
|
|
$where[] = qsprintf(
|
|
$conn_r,
|
|
'field.field = %s',
|
|
$field);
|
|
}
|
|
}
|
|
|
|
$exclude = $query->getParameter('exclude');
|
|
if ($exclude) {
|
|
$where[] = qsprintf($conn_r, 'document.phid != %s', $exclude);
|
|
}
|
|
|
|
if ($query->getParameter('type')) {
|
|
if (strlen($q)) {
|
|
// TODO: verify that this column actually does something useful in query
|
|
// plans once we have nontrivial amounts of data.
|
|
$where[] = qsprintf(
|
|
$conn_r,
|
|
'field.phidType = %s',
|
|
$query->getParameter('type'));
|
|
}
|
|
$where[] = qsprintf(
|
|
$conn_r,
|
|
'document.documentType = %s',
|
|
$query->getParameter('type'));
|
|
}
|
|
|
|
$join[] = $this->joinRelationship(
|
|
$conn_r,
|
|
$query,
|
|
'author',
|
|
PhabricatorSearchRelationship::RELATIONSHIP_AUTHOR);
|
|
|
|
$join[] = $this->joinRelationship(
|
|
$conn_r,
|
|
$query,
|
|
'open',
|
|
PhabricatorSearchRelationship::RELATIONSHIP_OPEN);
|
|
|
|
$join[] = $this->joinRelationship(
|
|
$conn_r,
|
|
$query,
|
|
'owner',
|
|
PhabricatorSearchRelationship::RELATIONSHIP_OWNER);
|
|
|
|
$join[] = $this->joinRelationship(
|
|
$conn_r,
|
|
$query,
|
|
'project',
|
|
PhabricatorSearchRelationship::RELATIONSHIP_PROJECT);
|
|
|
|
$join[] = $this->joinRelationship(
|
|
$conn_r,
|
|
$query,
|
|
'repository',
|
|
PhabricatorSearchRelationship::RELATIONSHIP_REPOSITORY);
|
|
|
|
/*
|
|
$join[] = $this->joinRelationship(
|
|
$conn_r,
|
|
$query,
|
|
'reviewer',
|
|
AdjutantRelationship::RELATIONSHIP_REVIEWER);
|
|
$join[] = $this->joinRelationship(
|
|
$conn_r,
|
|
$query,
|
|
'subscriber',
|
|
AdjutantRelationship::RELATIONSHIP_SUBSCRIBER);
|
|
$join[] = $this->joinRelationship(
|
|
$conn_r,
|
|
$query,
|
|
'repository',
|
|
AdjutantRelationship::RELATIONSHIP_REPOSITORY);
|
|
*/
|
|
$join = array_filter($join);
|
|
|
|
foreach ($join as $key => $clause) {
|
|
$join[$key] = ' JOIN '.$clause;
|
|
}
|
|
$join = implode(' ', $join);
|
|
|
|
if ($where) {
|
|
$where = 'WHERE '.implode(' AND ', $where);
|
|
} else {
|
|
$where = '';
|
|
}
|
|
|
|
$offset = (int)$query->getParameter('offset', 0);
|
|
$limit = (int)$query->getParameter('limit', 25);
|
|
|
|
$hits = queryfx_all(
|
|
$conn_r,
|
|
'SELECT
|
|
document.phid
|
|
FROM %T document
|
|
%Q
|
|
%Q
|
|
GROUP BY document.phid
|
|
%Q
|
|
LIMIT %d, %d',
|
|
$t_doc,
|
|
$join,
|
|
$where,
|
|
$order,
|
|
$offset,
|
|
$limit);
|
|
|
|
return ipull($hits, 'phid');
|
|
}
|
|
|
|
protected function joinRelationship(
|
|
AphrontDatabaseConnection $conn,
|
|
PhabricatorSearchQuery $query,
|
|
$field,
|
|
$type) {
|
|
|
|
$phids = $query->getParameter($field, array());
|
|
if (!$phids) {
|
|
return null;
|
|
}
|
|
|
|
$is_existence = false;
|
|
switch ($type) {
|
|
case PhabricatorSearchRelationship::RELATIONSHIP_OPEN:
|
|
$is_existence = true;
|
|
break;
|
|
}
|
|
|
|
$sql = qsprintf(
|
|
$conn,
|
|
'%T AS %C ON %C.phid = document.phid AND %C.relation = %s',
|
|
id(new PhabricatorSearchDocumentRelationship())->getTableName(),
|
|
$field,
|
|
$field,
|
|
$field,
|
|
$type);
|
|
|
|
if (!$is_existence) {
|
|
$sql .= qsprintf(
|
|
$conn,
|
|
' AND %C.relatedPHID in (%Ls)',
|
|
$field,
|
|
$phids);
|
|
}
|
|
|
|
return $sql;
|
|
}
|
|
|
|
|
|
}
|