diff options
Diffstat (limited to 'classes')
-rw-r--r-- | classes/Fave.php | 13 | ||||
-rw-r--r-- | classes/Memcached_DataObject.php | 12 | ||||
-rw-r--r-- | classes/Notice.php | 132 | ||||
-rw-r--r-- | classes/Notice_tag.php | 11 | ||||
-rw-r--r-- | classes/Profile.php | 73 | ||||
-rw-r--r-- | classes/Reply.php | 11 | ||||
-rw-r--r-- | classes/User.php | 25 | ||||
-rw-r--r-- | classes/User_group.php | 11 |
8 files changed, 173 insertions, 115 deletions
diff --git a/classes/Fave.php b/classes/Fave.php index 3aa23e7b4..4a9cfaae0 100644 --- a/classes/Fave.php +++ b/classes/Fave.php @@ -85,6 +85,19 @@ class Fave extends Memcached_DataObject return $ids; } + /** + * Note that the sorting for this is by order of *fave* not order of *notice*. + * + * @fixme add since_id, max_id support? + * + * @param <type> $user_id + * @param <type> $own + * @param <type> $offset + * @param <type> $limit + * @param <type> $since_id + * @param <type> $max_id + * @return <type> + */ function _streamDirect($user_id, $own, $offset, $limit, $since_id, $max_id) { $fav = new Fave(); diff --git a/classes/Memcached_DataObject.php b/classes/Memcached_DataObject.php index 27bb5d3c9..f71bfd3da 100644 --- a/classes/Memcached_DataObject.php +++ b/classes/Memcached_DataObject.php @@ -339,10 +339,14 @@ class Memcached_DataObject extends Safe_DataObject $start = microtime(true); $fail = false; - try { - $result = parent::_query($string); - } catch (Exception $e) { - $fail = $e; + $result = null; + if (Event::handle('StartDBQuery', array($this, $string, &$result))) { + try { + $result = parent::_query($string); + } catch (Exception $e) { + $fail = $e; + } + Event::handle('EndDBQuery', array($this, $string, &$result)); } $delta = microtime(true) - $start; diff --git a/classes/Notice.php b/classes/Notice.php index c1150626b..6acf0c7c1 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -654,7 +654,7 @@ class Notice extends Memcached_DataObject $notice->selectAdd(); // clears it $notice->selectAdd('id'); - $notice->orderBy('id DESC'); + $notice->orderBy('created DESC, id DESC'); if (!is_null($offset)) { $notice->limit($offset, $limit); @@ -668,13 +668,8 @@ class Notice extends Memcached_DataObject $notice->whereAdd('is_local !='. Notice::GATEWAY); } - if ($since_id != 0) { - $notice->whereAdd('id > ' . $since_id); - } - - if ($max_id != 0) { - $notice->whereAdd('id <= ' . $max_id); - } + Notice::addWhereSinceId($notice, $since_id); + Notice::addWhereMaxId($notice, $max_id); $ids = array(); @@ -709,19 +704,14 @@ class Notice extends Memcached_DataObject $notice->conversation = $id; - $notice->orderBy('id DESC'); + $notice->orderBy('created DESC, id DESC'); if (!is_null($offset)) { $notice->limit($offset, $limit); } - if ($since_id != 0) { - $notice->whereAdd('id > ' . $since_id); - } - - if ($max_id != 0) { - $notice->whereAdd('id <= ' . $max_id); - } + Notice::addWhereSinceId($notice, $since_id); + Notice::addWhereMaxId($notice, $max_id); $ids = array(); @@ -1695,10 +1685,10 @@ class Notice extends Memcached_DataObject $notice->repeat_of = $this->id; - $notice->orderBy('created'); // NB: asc! + $notice->orderBy('created, id'); // NB: asc! - if (!is_null($offset)) { - $notice->limit($offset, $limit); + if (!is_null($limit)) { + $notice->limit(0, $limit); } $ids = array(); @@ -1978,4 +1968,108 @@ class Notice extends Memcached_DataObject $d = new DateTime($dateStr, new DateTimeZone('UTC')); return $d->format(DATE_W3C); } + + /** + * Look up the creation timestamp for a given notice ID, even + * if it's been deleted. + * + * @param int $id + * @return mixed string recorded creation timestamp, or false if can't be found + */ + public static function getAsTimestamp($id) + { + if (!$id) { + return false; + } + + $notice = Notice::staticGet('id', $id); + if ($notice) { + return $notice->created; + } + + $deleted = Deleted_notice::staticGet('id', $id); + if ($deleted) { + return $deleted->created; + } + + return false; + } + + /** + * Build an SQL 'where' fragment for timestamp-based sorting from a since_id + * parameter, matching notices posted after the given one (exclusive). + * + * If the referenced notice can't be found, will return false. + * + * @param int $id + * @param string $idField + * @param string $createdField + * @return mixed string or false if no match + */ + public static function whereSinceId($id, $idField='id', $createdField='created') + { + $since = Notice::getAsTimestamp($id); + if ($since) { + return sprintf("($createdField = '%s' and $idField > %d) or ($createdField > '%s')", $since, $id, $since); + } + return false; + } + + /** + * Build an SQL 'where' fragment for timestamp-based sorting from a since_id + * parameter, matching notices posted after the given one (exclusive), and + * if necessary add it to the data object's query. + * + * @param DB_DataObject $obj + * @param int $id + * @param string $idField + * @param string $createdField + * @return mixed string or false if no match + */ + public static function addWhereSinceId(DB_DataObject $obj, $id, $idField='id', $createdField='created') + { + $since = self::whereSinceId($id); + if ($since) { + $obj->whereAdd($since); + } + } + + /** + * Build an SQL 'where' fragment for timestamp-based sorting from a max_id + * parameter, matching notices posted before the given one (inclusive). + * + * If the referenced notice can't be found, will return false. + * + * @param int $id + * @param string $idField + * @param string $createdField + * @return mixed string or false if no match + */ + public static function whereMaxId($id, $idField='id', $createdField='created') + { + $max = Notice::getAsTimestamp($id); + if ($max) { + return sprintf("($createdField < '%s') or ($createdField = '%s' and $idField <= %d)", $max, $max, $id); + } + return false; + } + + /** + * Build an SQL 'where' fragment for timestamp-based sorting from a max_id + * parameter, matching notices posted before the given one (inclusive), and + * if necessary add it to the data object's query. + * + * @param DB_DataObject $obj + * @param int $id + * @param string $idField + * @param string $createdField + * @return mixed string or false if no match + */ + public static function addWhereMaxId(DB_DataObject $obj, $id, $idField='id', $createdField='created') + { + $max = self::whereMaxId($id); + if ($max) { + $obj->whereAdd($max); + } + } } diff --git a/classes/Notice_tag.php b/classes/Notice_tag.php index ea38bb350..c8031ddf3 100644 --- a/classes/Notice_tag.php +++ b/classes/Notice_tag.php @@ -55,15 +55,10 @@ class Notice_tag extends Memcached_DataObject $nt->selectAdd(); $nt->selectAdd('notice_id'); - if ($since_id != 0) { - $nt->whereAdd('notice_id > ' . $since_id); - } - - if ($max_id != 0) { - $nt->whereAdd('notice_id <= ' . $max_id); - } + Notice::addWhereSinceId($nt, $since_id, 'notice_id'); + Notice::addWhereMaxId($nt, $max_id, 'notice_id'); - $nt->orderBy('notice_id DESC'); + $nt->orderBy('created DESC, notice_id DESC'); if (!is_null($offset)) { $nt->limit($offset, $limit); diff --git a/classes/Profile.php b/classes/Profile.php index 1f959eb0d..977947b6f 100644 --- a/classes/Profile.php +++ b/classes/Profile.php @@ -215,26 +215,29 @@ class Profile extends Memcached_DataObject function _streamTaggedDirect($tag, $offset, $limit, $since_id, $max_id) { // XXX It would be nice to do this without a join + // (necessary to do it efficiently on accounts with long history) $notice = new Notice(); $query = "select id from notice join notice_tag on id=notice_id where tag='". $notice->escape($tag) . - "' and profile_id=" . $notice->escape($this->id); + "' and profile_id=" . intval($this->id); - if ($since_id != 0) { - $query .= " and id > $since_id"; + $since = Notice::whereSinceId($since_id, 'id', 'notice.created'); + if ($since) { + $query .= " and ($since)"; } - if ($max_id != 0) { - $query .= " and id <= $max_id"; + $max = Notice::whereMaxId($max_id, 'id', 'notice.created'); + if ($max) { + $query .= " and ($max)"; } - $query .= ' order by id DESC'; + $query .= ' order by notice.created DESC, id DESC'; if (!is_null($offset)) { - $query .= " LIMIT $limit OFFSET $offset"; + $query .= " LIMIT " . intval($limit) . " OFFSET " . intval($offset); } $notice->query($query); @@ -252,58 +255,22 @@ class Profile extends Memcached_DataObject { $notice = new Notice(); - // Temporary hack until notice_profile_id_idx is updated - // to (profile_id, id) instead of (profile_id, created, id). - // It's been falling back to PRIMARY instead, which is really - // very inefficient for a profile that hasn't posted in a few - // months. Even though forcing the index will cause a filesort, - // it's usually going to be better. - if (common_config('db', 'type') == 'mysql') { - $index = ''; - $query = - "select id from notice force index (notice_profile_id_idx) ". - "where profile_id=" . $notice->escape($this->id); - - if ($since_id != 0) { - $query .= " and id > $since_id"; - } - - if ($max_id != 0) { - $query .= " and id <= $max_id"; - } - - $query .= ' order by id DESC'; - - if (!is_null($offset)) { - $query .= " LIMIT $limit OFFSET $offset"; - } - - $notice->query($query); - } else { - $index = ''; - - $notice->profile_id = $this->id; - - $notice->selectAdd(); - $notice->selectAdd('id'); - - if ($since_id != 0) { - $notice->whereAdd('id > ' . $since_id); - } + $notice->profile_id = $this->id; - if ($max_id != 0) { - $notice->whereAdd('id <= ' . $max_id); - } + $notice->selectAdd(); + $notice->selectAdd('id'); - $notice->orderBy('id DESC'); + Notice::addWhereSinceId($notice, $since_id); + Notice::addWhereMaxId($notice, $max_id); - if (!is_null($offset)) { - $notice->limit($offset, $limit); - } + $notice->orderBy('created DESC, id DESC'); - $notice->find(); + if (!is_null($offset)) { + $notice->limit($offset, $limit); } + $notice->find(); + $ids = array(); while ($notice->fetch()) { diff --git a/classes/Reply.php b/classes/Reply.php index da8a4f685..371c16cf4 100644 --- a/classes/Reply.php +++ b/classes/Reply.php @@ -50,15 +50,10 @@ class Reply extends Memcached_DataObject $reply = new Reply(); $reply->profile_id = $user_id; - if ($since_id != 0) { - $reply->whereAdd('notice_id > ' . $since_id); - } - - if ($max_id != 0) { - $reply->whereAdd('notice_id <= ' . $max_id); - } + Notice::addWhereSinceId($reply, $since_id, 'notice_id', 'modified'); + Notice::addWhereMaxId($reply, $max_id, 'notice_id', 'modified'); - $reply->orderBy('notice_id DESC'); + $reply->orderBy('modified DESC, notice_id DESC'); if (!is_null($offset)) { $reply->limit($offset, $limit); diff --git a/classes/User.php b/classes/User.php index 4baa6d1b3..04b9b4cc6 100644 --- a/classes/User.php +++ b/classes/User.php @@ -750,19 +750,14 @@ class User extends Memcached_DataObject $notice->profile_id = $this->id; $notice->whereAdd('repeat_of IS NOT NULL'); - $notice->orderBy('id DESC'); + $notice->orderBy('created DESC, id DESC'); if (!is_null($offset)) { $notice->limit($offset, $limit); } - if ($since_id != 0) { - $notice->whereAdd('id > ' . $since_id); - } - - if ($max_id != 0) { - $notice->whereAdd('id <= ' . $max_id); - } + Notice::addWhereSinceId($notice, $since_id); + Notice::addWhereMaxId($notice, $max_id); $ids = array(); @@ -795,17 +790,17 @@ class User extends Memcached_DataObject 'FROM notice original JOIN notice rept ON original.id = rept.repeat_of ' . 'WHERE original.profile_id = ' . $this->id . ' '; - if ($since_id != 0) { - $qry .= 'AND original.id > ' . $since_id . ' '; + $since = Notice::whereSinceId($since_id, 'original.id', 'original.created'); + if ($since) { + $qry .= "AND ($since) "; } - if ($max_id != 0) { - $qry .= 'AND original.id <= ' . $max_id . ' '; + $max = Notice::whereMaxId($max_id, 'original.id', 'original.created'); + if ($max) { + $qry .= "AND ($max) "; } - // NOTE: we sort by fave time, not by notice time! - - $qry .= 'ORDER BY original.id DESC '; + $qry .= 'ORDER BY original.created, original.id DESC '; if (!is_null($offset)) { $qry .= "LIMIT $limit OFFSET $offset"; diff --git a/classes/User_group.php b/classes/User_group.php index 60217e960..cffc78645 100644 --- a/classes/User_group.php +++ b/classes/User_group.php @@ -100,15 +100,10 @@ class User_group extends Memcached_DataObject $inbox->selectAdd(); $inbox->selectAdd('notice_id'); - if ($since_id != 0) { - $inbox->whereAdd('notice_id > ' . $since_id); - } - - if ($max_id != 0) { - $inbox->whereAdd('notice_id <= ' . $max_id); - } + Notice::addWhereSinceId($inbox, $since_id, 'notice_id'); + Notice::addWhereMaxId($inbox, $max_id, 'notice_id'); - $inbox->orderBy('notice_id DESC'); + $inbox->orderBy('created DESC, notice_id DESC'); if (!is_null($offset)) { $inbox->limit($offset, $limit); |