From 4d8b04cda93b0c2397a7544b9575dee3681fc085 Mon Sep 17 00:00:00 2001 From: Alexei Sorokin Date: Mon, 21 Sep 2020 22:25:33 +0300 Subject: [PATCH] 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. --- classes/Memcached_DataObject.php | 6 +----- lib/notices/inboxnoticestream.php | 2 +- plugins/Autocomplete/actions/autocomplete.php | 14 +++++++------- 3 files changed, 9 insertions(+), 13 deletions(-) diff --git a/classes/Memcached_DataObject.php b/classes/Memcached_DataObject.php index 6cb60e3802..d2140e3497 100644 --- a/classes/Memcached_DataObject.php +++ b/classes/Memcached_DataObject.php @@ -128,7 +128,7 @@ class Memcached_DataObject extends Safe_DataObject $join_tablename = common_database_tablename( $obj->tableName() . '_vals' ); - $join_keyword = ($preserve ? 'RIGHT' : 'LEFT') . ' JOIN'; + $join_keyword = ($preserve ? 'RIGHT' : 'INNER') . ' JOIN'; $vals_cast_type = ($col_type === 'int') ? 'INTEGER' : 'TEXT'; // 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 if ($skipNulls) { $obj->whereAdd("{$obj->escapedTableName()}.{$keyCol} IS NOT NULL"); diff --git a/lib/notices/inboxnoticestream.php b/lib/notices/inboxnoticestream.php index 3f48b6a3bb..7293b14c30 100644 --- a/lib/notices/inboxnoticestream.php +++ b/lib/notices/inboxnoticestream.php @@ -126,7 +126,7 @@ class RawInboxNoticeStream extends FullNoticeStream // managed to post here. $notice->query(sprintf( <<<'END' - SELECT id + SELECT DISTINCT id FROM ( ( SELECT notice.id diff --git a/plugins/Autocomplete/actions/autocomplete.php b/plugins/Autocomplete/actions/autocomplete.php index 37014c99b9..0c79b06c21 100644 --- a/plugins/Autocomplete/actions/autocomplete.php +++ b/plugins/Autocomplete/actions/autocomplete.php @@ -97,8 +97,8 @@ class AutocompleteAction extends Action $this->groups = []; $this->profiles = []; $term = $this->arg('term'); - $limit = $this->arg('limit'); - // prevent DOS attacks + $limit = (int) $this->arg('limit'); + // Prevent DOS attacks if ($limit > 200) { $limit = 200; } @@ -109,17 +109,17 @@ class AutocompleteAction extends Action $profile = new Profile(); $profile->_join .= sprintf( "\n" . <<<'END' - LEFT JOIN ( + INNER JOIN ( SELECT id FROM %s - UNION ALL + UNION SELECT subscribed AS id FROM subscription WHERE subscriber = %d ) AS t1 USING (id) END, $user_table, $this->scoped->id ); - $profile->whereAdd('t1.id IS NOT NULL'); $profile->whereAdd('nickname LIKE \'' . trim($profile->escape($term), '\'') . '%\''); + $profile->orderBy('created, id'); $profile->limit($limit); if ($profile->find()) { @@ -127,8 +127,7 @@ class AutocompleteAction extends Action $this->profiles[] = clone($profile); } } - } - if (substr($term, 0, 1) === '!') { + } elseif (substr($term, 0, 1) === '!') { //group search $term = substr($term, 1); $group = new User_group(); @@ -138,6 +137,7 @@ class AutocompleteAction extends Action $this->scoped->id )); $group->whereAdd('nickname LIKE \'' . trim($group->escape($term), '\'') . '%\''); + $group->orderBy('created, id'); $group->limit($limit); if ($group->find()) {