Clear out potential duplicates when semi-joining a union

Using a left outer join as a semi-join is not a valid approach.
Can still be used for an anti-semi-join.
This commit is contained in:
Alexei Sorokin 2020-09-21 22:25:33 +03:00 committed by Diogo Peralta Cordeiro
parent 318d2cb6ca
commit 8181b28441
3 changed files with 9 additions and 13 deletions

View File

@ -128,7 +128,7 @@ class Memcached_DataObject extends Safe_DataObject
$join_tablename = common_database_tablename( $join_tablename = common_database_tablename(
$obj->tableName() . '_vals' $obj->tableName() . '_vals'
); );
$join_keyword = ($preserve ? 'RIGHT' : 'LEFT') . ' JOIN'; $join_keyword = ($preserve ? 'RIGHT' : 'INNER') . ' JOIN';
$vals_cast_type = ($col_type === 'int') ? 'INTEGER' : 'TEXT'; $vals_cast_type = ($col_type === 'int') ? 'INTEGER' : 'TEXT';
// A lot of magic to ensure we get an ordered reply with the same exact // A lot of magic to ensure we get an ordered reply with the same exact
@ -179,10 +179,6 @@ class Memcached_DataObject extends Safe_DataObject
); );
} }
if (!$preserve) {
// Implements a left semi-join
$obj->whereAdd("{$join_tablename}.{$keyCol}_pos IS NOT NULL");
}
// Filters both NULLs requested and non-matching NULLs // Filters both NULLs requested and non-matching NULLs
if ($skipNulls) { if ($skipNulls) {
$obj->whereAdd("{$obj->escapedTableName()}.{$keyCol} IS NOT NULL"); $obj->whereAdd("{$obj->escapedTableName()}.{$keyCol} IS NOT NULL");

View File

@ -126,7 +126,7 @@ class RawInboxNoticeStream extends FullNoticeStream
// managed to post here. // managed to post here.
$notice->query(sprintf( $notice->query(sprintf(
<<<'END' <<<'END'
SELECT id SELECT DISTINCT id
FROM ( FROM (
( (
SELECT notice.id SELECT notice.id

View File

@ -97,8 +97,8 @@ class AutocompleteAction extends Action
$this->groups = []; $this->groups = [];
$this->profiles = []; $this->profiles = [];
$term = $this->arg('term'); $term = $this->arg('term');
$limit = $this->arg('limit'); $limit = (int) $this->arg('limit');
// prevent DOS attacks // Prevent DOS attacks
if ($limit > 200) { if ($limit > 200) {
$limit = 200; $limit = 200;
} }
@ -109,17 +109,17 @@ class AutocompleteAction extends Action
$profile = new Profile(); $profile = new Profile();
$profile->_join .= sprintf( $profile->_join .= sprintf(
"\n" . <<<'END' "\n" . <<<'END'
LEFT JOIN ( INNER JOIN (
SELECT id FROM %s SELECT id FROM %s
UNION ALL UNION
SELECT subscribed AS id FROM subscription WHERE subscriber = %d SELECT subscribed AS id FROM subscription WHERE subscriber = %d
) AS t1 USING (id) ) AS t1 USING (id)
END, END,
$user_table, $user_table,
$this->scoped->id $this->scoped->id
); );
$profile->whereAdd('t1.id IS NOT NULL');
$profile->whereAdd('nickname LIKE \'' . trim($profile->escape($term), '\'') . '%\''); $profile->whereAdd('nickname LIKE \'' . trim($profile->escape($term), '\'') . '%\'');
$profile->orderBy('created, id');
$profile->limit($limit); $profile->limit($limit);
if ($profile->find()) { if ($profile->find()) {
@ -127,8 +127,7 @@ class AutocompleteAction extends Action
$this->profiles[] = clone($profile); $this->profiles[] = clone($profile);
} }
} }
} } elseif (substr($term, 0, 1) === '!') {
if (substr($term, 0, 1) === '!') {
//group search //group search
$term = substr($term, 1); $term = substr($term, 1);
$group = new User_group(); $group = new User_group();
@ -138,6 +137,7 @@ class AutocompleteAction extends Action
$this->scoped->id $this->scoped->id
)); ));
$group->whereAdd('nickname LIKE \'' . trim($group->escape($term), '\'') . '%\''); $group->whereAdd('nickname LIKE \'' . trim($group->escape($term), '\'') . '%\'');
$group->orderBy('created, id');
$group->limit($limit); $group->limit($limit);
if ($group->find()) { if ($group->find()) {