summaryrefslogtreecommitdiff
path: root/classes
diff options
context:
space:
mode:
Diffstat (limited to 'classes')
-rw-r--r--classes/Fave.php13
-rw-r--r--classes/Memcached_DataObject.php12
-rw-r--r--classes/Notice.php132
-rw-r--r--classes/Notice_tag.php11
-rw-r--r--classes/Profile.php73
-rw-r--r--classes/Reply.php11
-rw-r--r--classes/User.php25
-rw-r--r--classes/User_group.php11
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);