Differential D18503 Diff 44448 src/infrastructure/query/policy/PhabricatorCursorPagedPolicyAwareQuery.php
Changeset View
Changeset View
Standalone View
Standalone View
src/infrastructure/query/policy/PhabricatorCursorPagedPolicyAwareQuery.php
| Show All 23 Lines | abstract class PhabricatorCursorPagedPolicyAwareQuery | ||||
| private $builtinOrder; | private $builtinOrder; | ||||
| private $edgeLogicConstraints = array(); | private $edgeLogicConstraints = array(); | ||||
| private $edgeLogicConstraintsAreValid = false; | private $edgeLogicConstraintsAreValid = false; | ||||
| private $spacePHIDs; | private $spacePHIDs; | ||||
| private $spaceIsArchived; | private $spaceIsArchived; | ||||
| private $ngrams = array(); | private $ngrams = array(); | ||||
| private $ferretEngine; | private $ferretEngine; | ||||
| private $ferretTokens; | private $ferretTokens; | ||||
| private $ferretTables; | |||||
| protected function getPageCursors(array $page) { | protected function getPageCursors(array $page) { | ||||
| return array( | return array( | ||||
| $this->getResultCursor(head($page)), | $this->getResultCursor(head($page)), | ||||
| $this->getResultCursor(last($page)), | $this->getResultCursor(last($page)), | ||||
| ); | ); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 1,356 Lines • ▼ Show 20 Lines | public function withFerretConstraint( | ||||
| if (!$fulltext_tokens) { | if (!$fulltext_tokens) { | ||||
| return $this; | return $this; | ||||
| } | } | ||||
| $this->ferretEngine = $engine; | $this->ferretEngine = $engine; | ||||
| $this->ferretTokens = $fulltext_tokens; | $this->ferretTokens = $fulltext_tokens; | ||||
| $function_map = array( | |||||
| 'all' => PhabricatorSearchDocumentFieldType::FIELD_ALL, | |||||
| 'title' => PhabricatorSearchDocumentFieldType::FIELD_TITLE, | |||||
| ); | |||||
| $current_function = 'all'; | |||||
| $table_map = array(); | |||||
| $idx = 1; | |||||
| foreach ($this->ferretTokens as $fulltext_token) { | |||||
| $raw_token = $fulltext_token->getToken(); | |||||
| $function = $raw_token->getFunction(); | |||||
| if ($function === null) { | |||||
| $function = $current_function; | |||||
| } | |||||
| if (!isset($function_map[$function])) { | |||||
| throw new PhutilSearchQueryCompilerSyntaxException( | |||||
| pht( | |||||
| 'Unknown search function "%s".', | |||||
| $function)); | |||||
| } | |||||
| if (!isset($table_map[$function])) { | |||||
| $alias = 'ftfield'.$idx++; | |||||
| $table_map[$function] = array( | |||||
| 'alias' => $alias, | |||||
| 'key' => $function_map[$function], | |||||
| ); | |||||
| } | |||||
| $current_function = $function; | |||||
| } | |||||
| $this->ferretTables = $table_map; | |||||
| return $this; | return $this; | ||||
| } | } | ||||
| protected function buildFerretJoinClause(AphrontDatabaseConnection $conn) { | protected function buildFerretJoinClause(AphrontDatabaseConnection $conn) { | ||||
| if (!$this->ferretEngine) { | if (!$this->ferretEngine) { | ||||
| return array(); | return array(); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 108 Lines • ▼ Show 20 Lines | foreach ($flat as $spec) { | ||||
| 'JOIN %T %T ON %T.documentID = ftdoc.id AND %T.ngram = %s', | 'JOIN %T %T ON %T.documentID = ftdoc.id AND %T.ngram = %s', | ||||
| $table, | $table, | ||||
| $alias, | $alias, | ||||
| $alias, | $alias, | ||||
| $alias, | $alias, | ||||
| $ngram); | $ngram); | ||||
| } | } | ||||
| foreach ($this->ferretTables as $table) { | |||||
| $alias = $table['alias']; | |||||
| $joins[] = qsprintf( | $joins[] = qsprintf( | ||||
| $conn, | $conn, | ||||
| 'JOIN %T ftfield ON ftdoc.id = ftfield.documentID', | 'JOIN %T %T ON ftdoc.id = %T.documentID | ||||
| $field_table->getTableName()); | AND %T.fieldKey = %s', | ||||
| $field_table->getTableName(), | |||||
| $alias, | |||||
| $alias, | |||||
| $alias, | |||||
| $table['key']); | |||||
| } | |||||
| return $joins; | return $joins; | ||||
| } | } | ||||
| protected function buildFerretWhereClause(AphrontDatabaseConnection $conn) { | protected function buildFerretWhereClause(AphrontDatabaseConnection $conn) { | ||||
| if (!$this->ferretEngine) { | if (!$this->ferretEngine) { | ||||
| return array(); | return array(); | ||||
| } | } | ||||
| $ngram_engine = new PhabricatorNgramEngine(); | $ngram_engine = new PhabricatorNgramEngine(); | ||||
| $stemmer = new PhutilSearchStemmer(); | $stemmer = new PhutilSearchStemmer(); | ||||
| $table_map = $this->ferretTables; | |||||
| $op_sub = PhutilSearchQueryCompiler::OPERATOR_SUBSTRING; | $op_sub = PhutilSearchQueryCompiler::OPERATOR_SUBSTRING; | ||||
| $op_not = PhutilSearchQueryCompiler::OPERATOR_NOT; | $op_not = PhutilSearchQueryCompiler::OPERATOR_NOT; | ||||
| $where = array(); | $where = array(); | ||||
| $current_function = 'all'; | |||||
| foreach ($this->ferretTokens as $fulltext_token) { | foreach ($this->ferretTokens as $fulltext_token) { | ||||
| $raw_token = $fulltext_token->getToken(); | $raw_token = $fulltext_token->getToken(); | ||||
| $value = $raw_token->getValue(); | $value = $raw_token->getValue(); | ||||
| $function = $raw_token->getFunction(); | |||||
| if ($function === null) { | |||||
| $function = $current_function; | |||||
| } | |||||
| $current_function = $function; | |||||
| $table_alias = $table_map[$function]['alias']; | |||||
| $is_not = ($raw_token->getOperator() == $op_not); | $is_not = ($raw_token->getOperator() == $op_not); | ||||
| if ($raw_token->getOperator() == $op_sub) { | if ($raw_token->getOperator() == $op_sub) { | ||||
| $is_substring = true; | $is_substring = true; | ||||
| } else { | } else { | ||||
| $is_substring = false; | $is_substring = false; | ||||
| } | } | ||||
| // If we're doing substring search, we just match against the raw corpus | // If we're doing substring search, we just match against the raw corpus | ||||
| // and we're done. | // and we're done. | ||||
| if ($is_substring) { | if ($is_substring) { | ||||
| if ($is_not) { | if ($is_not) { | ||||
| $where[] = qsprintf( | $where[] = qsprintf( | ||||
| $conn, | $conn, | ||||
| '(ftfield.rawCorpus NOT LIKE %~)', | '(%T.rawCorpus NOT LIKE %~)', | ||||
| $table_alias, | |||||
| $value); | $value); | ||||
| } else { | } else { | ||||
| $where[] = qsprintf( | $where[] = qsprintf( | ||||
| $conn, | $conn, | ||||
| '(ftfield.rawCorpus LIKE %~)', | '(%T.rawCorpus LIKE %~)', | ||||
| $table_alias, | |||||
| $value); | $value); | ||||
| } | } | ||||
| continue; | continue; | ||||
| } | } | ||||
| // Otherwise, we need to match against the term corpus and the normal | // Otherwise, we need to match against the term corpus and the normal | ||||
| // corpus, so that searching for "raw" does not find "strawberry". | // corpus, so that searching for "raw" does not find "strawberry". | ||||
| if ($raw_token->isQuoted()) { | if ($raw_token->isQuoted()) { | ||||
| Show All 11 Lines | foreach ($this->ferretTokens as $fulltext_token) { | ||||
| } | } | ||||
| $term_constraints = array(); | $term_constraints = array(); | ||||
| $term_value = ' '.$ngram_engine->newTermsCorpus($value).' '; | $term_value = ' '.$ngram_engine->newTermsCorpus($value).' '; | ||||
| if ($is_not) { | if ($is_not) { | ||||
| $term_constraints[] = qsprintf( | $term_constraints[] = qsprintf( | ||||
| $conn, | $conn, | ||||
| '(ftfield.termCorpus NOT LIKE %~)', | '(%T.termCorpus NOT LIKE %~)', | ||||
| $table_alias, | |||||
| $term_value); | $term_value); | ||||
| } else { | } else { | ||||
| $term_constraints[] = qsprintf( | $term_constraints[] = qsprintf( | ||||
| $conn, | $conn, | ||||
| '(ftfield.termCorpus LIKE %~)', | '(%T.termCorpus LIKE %~)', | ||||
| $table_alias, | |||||
| $term_value); | $term_value); | ||||
| } | } | ||||
| if ($is_stemmed) { | if ($is_stemmed) { | ||||
| $stem_value = $stemmer->stemToken($value); | $stem_value = $stemmer->stemToken($value); | ||||
| $stem_value = $ngram_engine->newTermsCorpus($stem_value); | $stem_value = $ngram_engine->newTermsCorpus($stem_value); | ||||
| $stem_value = ' '.$stem_value.' '; | $stem_value = ' '.$stem_value.' '; | ||||
| $term_constraints[] = qsprintf( | $term_constraints[] = qsprintf( | ||||
| $conn, | $conn, | ||||
| '(ftfield.normalCorpus LIKE %~)', | '(%T.normalCorpus LIKE %~)', | ||||
| $table_alias, | |||||
| $stem_value); | $stem_value); | ||||
| } | } | ||||
| if ($is_not) { | if ($is_not) { | ||||
| $where[] = qsprintf( | $where[] = qsprintf( | ||||
| $conn, | $conn, | ||||
| '(%Q)', | '(%Q)', | ||||
| implode(' AND ', $term_constraints)); | implode(' AND ', $term_constraints)); | ||||
| } else if ($is_quoted) { | } else if ($is_quoted) { | ||||
| $where[] = qsprintf( | $where[] = qsprintf( | ||||
| $conn, | $conn, | ||||
| '(ftfield.rawCorpus LIKE %~ AND (%Q))', | '(%T.rawCorpus LIKE %~ AND (%Q))', | ||||
| $table_alias, | |||||
| $value, | $value, | ||||
| implode(' OR ', $term_constraints)); | implode(' OR ', $term_constraints)); | ||||
| } else { | } else { | ||||
| $where[] = qsprintf( | $where[] = qsprintf( | ||||
| $conn, | $conn, | ||||
| '(%Q)', | '(%Q)', | ||||
| implode(' OR ', $term_constraints)); | implode(' OR ', $term_constraints)); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 762 Lines • Show Last 20 Lines | |||||