Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F15331673
D21110.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
4 KB
Referenced Files
None
Subscribers
None
D21110.diff
View Options
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
@@ -1801,24 +1801,35 @@
$this->ferretEngine = $engine;
$this->ferretTokens = $fulltext_tokens;
+ $op_absent = PhutilSearchQueryCompiler::OPERATOR_ABSENT;
+
$default_function = $engine->getDefaultFunctionKey();
$table_map = array();
$idx = 1;
foreach ($this->ferretTokens as $fulltext_token) {
$raw_token = $fulltext_token->getToken();
- $function = $raw_token->getFunction();
+ $function = $raw_token->getFunction();
if ($function === null) {
$function = $default_function;
}
$raw_field = $engine->getFieldForFunction($function);
+ // NOTE: The query compiler guarantees that a query can not make a
+ // field both "present" and "absent", so it's safe to just use the
+ // first operator we encounter to determine whether the table is
+ // optional or not.
+
+ $operator = $raw_token->getOperator();
+ $is_optional = ($operator === $op_absent);
+
if (!isset($table_map[$function])) {
$alias = 'ftfield_'.$idx++;
$table_map[$function] = array(
'alias' => $alias,
'key' => $raw_field,
+ 'optional' => $is_optional,
);
}
}
@@ -1966,6 +1977,8 @@
$op_sub = PhutilSearchQueryCompiler::OPERATOR_SUBSTRING;
$op_not = PhutilSearchQueryCompiler::OPERATOR_NOT;
+ $op_absent = PhutilSearchQueryCompiler::OPERATOR_ABSENT;
+ $op_present = PhutilSearchQueryCompiler::OPERATOR_PRESENT;
$engine = $this->ferretEngine;
$stemmer = $engine->newStemmer();
@@ -1976,11 +1989,19 @@
foreach ($this->ferretTokens as $fulltext_token) {
$raw_token = $fulltext_token->getToken();
+ $operator = $raw_token->getOperator();
+
// If this is a negated term like "-pomegranate", don't join the ngram
// table since we aren't looking for documents with this term. (We could
// LEFT JOIN the table and require a NULL row, but this is probably more
// trouble than it's worth.)
- if ($raw_token->getOperator() == $op_not) {
+ if ($operator === $op_not) {
+ continue;
+ }
+
+ // Neither the "present" or "absent" operators benefit from joining
+ // the ngram table.
+ if ($operator === $op_absent || $operator === $op_present) {
continue;
}
@@ -2143,31 +2164,54 @@
$op_sub = PhutilSearchQueryCompiler::OPERATOR_SUBSTRING;
$op_not = PhutilSearchQueryCompiler::OPERATOR_NOT;
$op_exact = PhutilSearchQueryCompiler::OPERATOR_EXACT;
+ $op_absent = PhutilSearchQueryCompiler::OPERATOR_ABSENT;
+ $op_present = PhutilSearchQueryCompiler::OPERATOR_PRESENT;
$where = array();
- $current_function = 'all';
+ $default_function = $engine->getDefaultFunctionKey();
foreach ($this->ferretTokens as $fulltext_token) {
$raw_token = $fulltext_token->getToken();
$value = $raw_token->getValue();
$function = $raw_token->getFunction();
if ($function === null) {
- $function = $current_function;
+ $function = $default_function;
}
- $current_function = $function;
+
+ $operator = $raw_token->getOperator();
$table_alias = $table_map[$function]['alias'];
- $is_not = ($raw_token->getOperator() == $op_not);
+ // If this is a "field is present" operator, we've already implicitly
+ // guaranteed this by JOINing the table. We don't need to do any
+ // more work.
+ $is_present = ($operator === $op_present);
+ if ($is_present) {
+ continue;
+ }
- if ($raw_token->getOperator() == $op_sub) {
+ // If this is a "field is absent" operator, we just want documents
+ // which failed to match to a row when we LEFT JOINed the table. This
+ // means there's no index for the field.
+ $is_absent = ($operator === $op_absent);
+ if ($is_absent) {
+ $where[] = qsprintf(
+ $conn,
+ '(%T.rawCorpus IS NULL)',
+ $table_alias);
+ continue;
+ }
+
+ $is_not = ($operator === $op_not);
+
+ if ($operator == $op_sub) {
$is_substring = true;
} else {
$is_substring = false;
}
// If we're doing exact search, just test the raw corpus.
- $is_exact = ($raw_token->getOperator() == $op_exact);
+ $is_exact = ($operator === $op_exact);
if ($is_exact) {
if ($is_not) {
$where[] = qsprintf(
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Mar 8, 12:36 PM (2 w, 2 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7382345
Default Alt Text
D21110.diff (4 KB)
Attached To
Mode
D21110: Implement the "present" and "absent" operators in the Ferret execution engine
Attached
Detach File
Event Timeline
Log In to Comment