The thread table is replaced by post-thread and post-thread-user
authorMichael <heluecht@pirati.ca>
Thu, 4 Feb 2021 05:51:25 +0000 (05:51 +0000)
committerMichael <heluecht@pirati.ca>
Thu, 4 Feb 2021 05:51:25 +0000 (05:51 +0000)
13 files changed:
database.sql
include/api.php
mod/notes.php
src/Model/Item.php
src/Model/Post.php
src/Model/Post/Thread.php [new file with mode: 0644]
src/Module/Conversation/Community.php
src/Worker/Expire.php
src/Worker/ExpirePosts.php
src/Worker/RemoveUnusedContacts.php
static/dbstructure.config.php
static/dbview.config.php
update.php

index 60dca5f..98aa162 100644 (file)
@@ -1,6 +1,6 @@
 -- ------------------------------------------
 -- Friendica 2021.03-dev (Red Hot Poker)
--- DB_UPDATE_VERSION 1397
+-- DB_UPDATE_VERSION 1398
 -- ------------------------------------------
 
 
@@ -1125,6 +1125,32 @@ CREATE TABLE IF NOT EXISTS `post-tag` (
        FOREIGN KEY (`cid`) REFERENCES `contact` (`id`) ON UPDATE RESTRICT ON DELETE RESTRICT
 ) DEFAULT COLLATE utf8mb4_general_ci COMMENT='post relation to tags';
 
+--
+-- TABLE post-thread
+--
+CREATE TABLE IF NOT EXISTS `post-thread` (
+       `uri-id` int unsigned NOT NULL COMMENT 'Id of the item-uri table entry that contains the item uri',
+       `owner-id` int unsigned NOT NULL DEFAULT 0 COMMENT 'Item owner',
+       `author-id` int unsigned NOT NULL DEFAULT 0 COMMENT 'Item author',
+       `causer-id` int unsigned NOT NULL DEFAULT 0 COMMENT 'Link to the contact table with uid=0 of the contact that caused the item creation',
+       `network` char(4) NOT NULL DEFAULT '' COMMENT '',
+       `created` datetime NOT NULL DEFAULT '0001-01-01 00:00:00' COMMENT '',
+       `received` datetime NOT NULL DEFAULT '0001-01-01 00:00:00' COMMENT '',
+       `changed` datetime NOT NULL DEFAULT '0001-01-01 00:00:00' COMMENT 'Date that something in the conversation changed, indicating clients should fetch the conversation again',
+       `commented` datetime NOT NULL DEFAULT '0001-01-01 00:00:00' COMMENT '',
+        PRIMARY KEY(`uri-id`),
+        INDEX `owner-id` (`owner-id`),
+        INDEX `author-id` (`author-id`),
+        INDEX `causer-id` (`causer-id`),
+        INDEX `received` (`received`),
+        INDEX `commented` (`commented`),
+        INDEX `changed` (`changed`),
+       FOREIGN KEY (`uri-id`) REFERENCES `item-uri` (`id`) ON UPDATE RESTRICT ON DELETE CASCADE,
+       FOREIGN KEY (`owner-id`) REFERENCES `contact` (`id`) ON UPDATE RESTRICT ON DELETE RESTRICT,
+       FOREIGN KEY (`author-id`) REFERENCES `contact` (`id`) ON UPDATE RESTRICT ON DELETE RESTRICT,
+       FOREIGN KEY (`causer-id`) REFERENCES `contact` (`id`) ON UPDATE RESTRICT ON DELETE RESTRICT
+) DEFAULT COLLATE utf8mb4_general_ci COMMENT='Thread related data';
+
 --
 -- TABLE post-thread-user
 --
@@ -1135,6 +1161,7 @@ CREATE TABLE IF NOT EXISTS `post-thread-user` (
        `starred` boolean NOT NULL DEFAULT '0' COMMENT '',
        `ignored` boolean NOT NULL DEFAULT '0' COMMENT 'Ignore updates for this thread',
        `wall` boolean NOT NULL DEFAULT '0' COMMENT 'This item was posted to the wall of uid',
+       `mention` boolean NOT NULL DEFAULT '0' COMMENT '',
        `pubmail` boolean NOT NULL DEFAULT '0' COMMENT '',
        `forum_mode` tinyint unsigned NOT NULL DEFAULT 0 COMMENT '',
         PRIMARY KEY(`uid`,`uri-id`),
@@ -1641,43 +1668,43 @@ CREATE VIEW `post-view` AS SELECT
 DROP VIEW IF EXISTS `post-thread-view`;
 CREATE VIEW `post-thread-view` AS SELECT 
        `item`.`id` AS `id`,
-       `thread`.`iid` AS `iid`,
+       `item`.`id` AS `iid`,
        `item`.`id` AS `item_id`,
-       `thread`.`uid` AS `uid`,
+       `post-thread-user`.`uid` AS `uid`,
        `item`.`parent` AS `parent`,
        `item`.`uri` AS `uri`,
-       `item`.`uri-id` AS `uri-id`,
+       `post-thread`.`uri-id` AS `uri-id`,
        `item`.`parent-uri` AS `parent-uri`,
        `item`.`parent-uri-id` AS `parent-uri-id`,
        `item`.`thr-parent` AS `thr-parent`,
        `item`.`thr-parent-id` AS `thr-parent-id`,
        `item`.`guid` AS `guid`,
        `item`.`type` AS `type`,
-       `thread`.`wall` AS `wall`,
+       `post-thread-user`.`wall` AS `wall`,
        `item`.`gravity` AS `gravity`,
        `item`.`extid` AS `extid`,
-       `thread`.`created` AS `created`,
+       `post-thread`.`created` AS `created`,
        `item`.`edited` AS `edited`,
-       `thread`.`commented` AS `commented`,
-       `thread`.`received` AS `received`,
-       `thread`.`changed` AS `changed`,
-       `thread`.`post-type` AS `post-type`,
-       `thread`.`private` AS `private`,
-       `thread`.`pubmail` AS `pubmail`,
-       `thread`.`moderated` AS `moderated`,
-       `thread`.`ignored` AS `ignored`,
-       `thread`.`visible` AS `visible`,
-       `thread`.`starred` AS `starred`,
+       `post-thread`.`commented` AS `commented`,
+       `post-thread`.`received` AS `received`,
+       `post-thread`.`changed` AS `changed`,
+       `item`.`post-type` AS `post-type`,
+       `item`.`private` AS `private`,
+       `post-thread-user`.`pubmail` AS `pubmail`,
+       `item`.`moderated` AS `moderated`,
+       `post-thread-user`.`ignored` AS `ignored`,
+       `item`.`visible` AS `visible`,
+       `post-thread-user`.`starred` AS `starred`,
        `item`.`bookmark` AS `bookmark`,
-       `item`.`unseen` AS `unseen`,
-       `thread`.`deleted` AS `deleted`,
-       `thread`.`origin` AS `origin`,
-       `thread`.`forum_mode` AS `forum_mode`,
-       `thread`.`mention` AS `mention`,
+       `post-user`.`unseen` AS `unseen`,
+       `item`.`deleted` AS `deleted`,
+       `post-user`.`origin` AS `origin`,
+       `post-thread-user`.`forum_mode` AS `forum_mode`,
+       `item`.`mention` AS `mention`,
        `item`.`global` AS `global`,
-       `thread`.`network` AS `network`,
+       `post-thread`.`network` AS `network`,
        `item`.`vid` AS `vid`,
-       `item`.`psid` AS `psid`,
+       `post-user`.`psid` AS `psid`,
        IF (`item`.`vid` IS NULL, '', `verb`.`name`) AS `verb`,
        `post-content`.`title` AS `title`,
        `post-content`.`content-warning` AS `content-warning`,
@@ -1695,7 +1722,7 @@ CREATE VIEW `post-thread-view` AS SELECT
        `post-content`.`target-type` AS `target-type`,
        `post-content`.`target` AS `target`,
        `post-content`.`resource-id` AS `resource-id`,
-       `thread`.`contact-id` AS `contact-id`,
+       `post-user`.`contact-id` AS `contact-id`,
        `contact`.`url` AS `contact-link`,
        `contact`.`addr` AS `contact-addr`,
        `contact`.`name` AS `contact-name`,
@@ -1720,7 +1747,7 @@ CREATE VIEW `post-thread-view` AS SELECT
        `contact`.`avatar-date` AS `avatar-date`,
        `contact`.`thumb` AS `thumb`,
        `contact`.`dfrn-id` AS `dfrn-id`,
-       `thread`.`author-id` AS `author-id`,
+       `post-thread`.`author-id` AS `author-id`,
        `author`.`url` AS `author-link`,
        `author`.`addr` AS `author-addr`,
        IF (`contact`.`url` = `author`.`url` AND `contact`.`name` != '', `contact`.`name`, `author`.`name`) AS `author-name`,
@@ -1729,7 +1756,7 @@ CREATE VIEW `post-thread-view` AS SELECT
        `author`.`network` AS `author-network`,
        `author`.`blocked` AS `author-blocked`,
        `author`.`hidden` AS `author-hidden`,
-       `thread`.`owner-id` AS `owner-id`,
+       `post-thread`.`owner-id` AS `owner-id`,
        `owner`.`url` AS `owner-link`,
        `owner`.`addr` AS `owner-addr`,
        IF (`contact`.`url` = `owner`.`url` AND `contact`.`name` != '', `contact`.`name`, `owner`.`name`) AS `owner-name`,
@@ -1753,10 +1780,10 @@ CREATE VIEW `post-thread-view` AS SELECT
        `post-delivery-data`.`queue_count` AS `delivery_queue_count`,
        `post-delivery-data`.`queue_done` AS `delivery_queue_done`,
        `post-delivery-data`.`queue_failed` AS `delivery_queue_failed`,
-       IF (`item`.`psid` IS NULL, '', `permissionset`.`allow_cid`) AS `allow_cid`,
-       IF (`item`.`psid` IS NULL, '', `permissionset`.`allow_gid`) AS `allow_gid`,
-       IF (`item`.`psid` IS NULL, '', `permissionset`.`deny_cid`) AS `deny_cid`,
-       IF (`item`.`psid` IS NULL, '', `permissionset`.`deny_gid`) AS `deny_gid`,
+       IF (`post-user`.`psid` IS NULL, '', `permissionset`.`allow_cid`) AS `allow_cid`,
+       IF (`post-user`.`psid` IS NULL, '', `permissionset`.`allow_gid`) AS `allow_gid`,
+       IF (`post-user`.`psid` IS NULL, '', `permissionset`.`deny_cid`) AS `deny_cid`,
+       IF (`post-user`.`psid` IS NULL, '', `permissionset`.`deny_gid`) AS `deny_gid`,
        `item`.`event-id` AS `event-id`,
        `event`.`created` AS `event-created`,
        `event`.`edited` AS `event-edited`,
@@ -1776,18 +1803,20 @@ CREATE VIEW `post-thread-view` AS SELECT
        `parent-item-author`.`url` AS `parent-author-link`,
        `parent-item-author`.`name` AS `parent-author-name`,
        `parent-item-author`.`network` AS `parent-author-network`
-       FROM `thread`
-                       STRAIGHT_JOIN `item` ON `item`.`id` = `thread`.`iid`
-                       STRAIGHT_JOIN `contact` ON `contact`.`id` = `thread`.`contact-id`
-                       STRAIGHT_JOIN `contact` AS `author` ON `author`.`id` = `thread`.`author-id`
-                       STRAIGHT_JOIN `contact` AS `owner` ON `owner`.`id` = `thread`.`owner-id`
-                       STRAIGHT_JOIN `contact` AS `causer` ON `causer`.`id` = `item`.`causer-id`
+       FROM `post-thread`
+                       STRAIGHT_JOIN `post-thread-user` ON `post-thread-user`.`uri-id` = `post-thread`.`uri-id`
+                       STRAIGHT_JOIN `post-user` ON `post-user`.`uri-id` = `post-thread`.`uri-id`
+                       STRAIGHT_JOIN `item` ON `item`.`uri-id` = `post-thread`.`uri-id` AND `item`.`uid` = `post-thread-user`.`uid`
+                       STRAIGHT_JOIN `contact` ON `contact`.`id` = `post-user`.`contact-id`
+                       STRAIGHT_JOIN `contact` AS `author` ON `author`.`id` = `post-thread`.`author-id`
+                       STRAIGHT_JOIN `contact` AS `owner` ON `owner`.`id` = `post-thread`.`owner-id`
+                       STRAIGHT_JOIN `contact` AS `causer` ON `causer`.`id` = `post-thread`.`causer-id`
                        LEFT JOIN `verb` ON `verb`.`id` = `item`.`vid`
                        LEFT JOIN `event` ON `event`.`id` = `item`.`event-id`
-                       LEFT JOIN `diaspora-interaction` ON `diaspora-interaction`.`uri-id` = `thread`.`uri-id`
-                       LEFT JOIN `post-content` ON `post-content`.`uri-id` = `thread`.`uri-id`
-                       LEFT JOIN `post-delivery-data` ON `post-delivery-data`.`uri-id` = `thread`.`uri-id` AND `thread`.`origin`
-                       LEFT JOIN `permissionset` ON `permissionset`.`id` = `item`.`psid`
+                       LEFT JOIN `diaspora-interaction` ON `diaspora-interaction`.`uri-id` = `post-thread`.`uri-id`
+                       LEFT JOIN `post-content` ON `post-content`.`uri-id` = `post-thread`.`uri-id`
+                       LEFT JOIN `post-delivery-data` ON `post-delivery-data`.`uri-id` = `post-thread`.`uri-id` AND `post-user`.`origin`
+                       LEFT JOIN `permissionset` ON `permissionset`.`id` = `post-user`.`psid`
                        STRAIGHT_JOIN `item` AS `parent-item` ON `parent-item`.`id` = `item`.`parent`
                        STRAIGHT_JOIN `contact` AS `parent-item-author` ON `parent-item-author`.`id` = `parent-item`.`author-id`;
 
@@ -1846,13 +1875,13 @@ CREATE VIEW `network-item-view` AS SELECT
        `item`.`contact-id` AS `contact-id`,
        `ownercontact`.`contact-type` AS `contact-type`
        FROM `item`
-                       INNER JOIN `thread` ON `thread`.`iid` = `item`.`parent`
-                       STRAIGHT_JOIN `contact` ON `contact`.`id` = `thread`.`contact-id`
-                       LEFT JOIN `post-user` ON `post-user`.`uri-id` = `item`.`uri-id` AND `post-user`.`uid` = `thread`.`uid`
-                       LEFT JOIN `user-contact` AS `author` ON `author`.`uid` = `thread`.`uid` AND `author`.`cid` = `thread`.`author-id`
-                       LEFT JOIN `user-contact` AS `owner` ON `owner`.`uid` = `thread`.`uid` AND `owner`.`cid` = `thread`.`owner-id`
-                       LEFT JOIN `contact` AS `ownercontact` ON `ownercontact`.`id` = `thread`.`owner-id`
-                       WHERE `thread`.`visible` AND NOT `thread`.`deleted` AND NOT `thread`.`moderated`
+                       INNER JOIN `item` AS `parent-item` ON `parent-item`.`id` = `item`.`parent`
+                       STRAIGHT_JOIN `contact` ON `contact`.`id` = `parent-item`.`contact-id`
+                       LEFT JOIN `post-user` ON `post-user`.`uri-id` = `item`.`uri-id` AND `post-user`.`uid` = `parent-item`.`uid`
+                       LEFT JOIN `user-contact` AS `author` ON `author`.`uid` = `parent-item`.`uid` AND `author`.`cid` = `parent-item`.`author-id`
+                       LEFT JOIN `user-contact` AS `owner` ON `owner`.`uid` = `parent-item`.`uid` AND `owner`.`cid` = `parent-item`.`owner-id`
+                       LEFT JOIN `contact` AS `ownercontact` ON `ownercontact`.`id` = `parent-item`.`owner-id`
+                       WHERE `parent-item`.`visible` AND NOT `parent-item`.`deleted` AND NOT `parent-item`.`moderated`
                        AND (NOT `contact`.`readonly` AND NOT `contact`.`blocked` AND NOT `contact`.`pending`)
                        AND (`post-user`.`hidden` IS NULL OR NOT `post-user`.`hidden`)
                        AND (`author`.`blocked` IS NULL OR NOT `author`.`blocked`)
@@ -1863,27 +1892,28 @@ CREATE VIEW `network-item-view` AS SELECT
 --
 DROP VIEW IF EXISTS `network-thread-view`;
 CREATE VIEW `network-thread-view` AS SELECT 
-       `item`.`uri-id` AS `uri-id`,
+       `post-thread`.`uri-id` AS `uri-id`,
        `item`.`uri` AS `uri`,
        `item`.`parent-uri-id` AS `parent-uri-id`,
-       `thread`.`iid` AS `parent`,
-       `thread`.`received` AS `received`,
-       `thread`.`commented` AS `commented`,
-       `thread`.`created` AS `created`,
-       `thread`.`uid` AS `uid`,
-       `thread`.`starred` AS `starred`,
-       `thread`.`mention` AS `mention`,
-       `thread`.`network` AS `network`,
-       `thread`.`contact-id` AS `contact-id`,
+       `item`.`id` AS `parent`,
+       `post-thread`.`received` AS `received`,
+       `post-thread`.`commented` AS `commented`,
+       `post-thread`.`created` AS `created`,
+       `post-thread-user`.`uid` AS `uid`,
+       `post-thread-user`.`starred` AS `starred`,
+       `post-thread-user`.`mention` AS `mention`,
+       `post-thread`.`network` AS `network`,
+       `post-user`.`contact-id` AS `contact-id`,
        `ownercontact`.`contact-type` AS `contact-type`
-       FROM `thread`
-                       STRAIGHT_JOIN `contact` ON `contact`.`id` = `thread`.`contact-id`
-                       STRAIGHT_JOIN `item` ON `item`.`id` = `thread`.`iid`
-                       LEFT JOIN `post-user` ON `post-user`.`uri-id` = `item`.`uri-id` AND `post-user`.`uid` = `thread`.`uid`
-                       LEFT JOIN `user-contact` AS `author` ON `author`.`uid` = `thread`.`uid` AND `author`.`cid` = `thread`.`author-id`
-                       LEFT JOIN `user-contact` AS `owner` ON `owner`.`uid` = `thread`.`uid` AND `owner`.`cid` = `thread`.`owner-id`
-                       LEFT JOIN `contact` AS `ownercontact` ON `ownercontact`.`id` = `thread`.`owner-id`
-                       WHERE `thread`.`visible` AND NOT `thread`.`deleted` AND NOT `thread`.`moderated`
+       FROM `post-thread`
+                       STRAIGHT_JOIN `post-thread-user` ON `post-thread-user`.`uri-id` = `post-thread`.`uri-id`
+                       STRAIGHT_JOIN `post-user` ON `post-user`.`uri-id` = `post-thread`.`uri-id` AND `post-user`.`uid` = `post-thread-user`.`uid`
+                       STRAIGHT_JOIN `item` ON `item`.`uri-id` = `post-thread`.`uri-id` AND `item`.`uid` = `post-thread-user`.`uid`
+                       STRAIGHT_JOIN `contact` ON `contact`.`id` = `post-user`.`contact-id`
+                       LEFT JOIN `user-contact` AS `author` ON `author`.`uid` = `post-user`.`uid` AND `author`.`cid` = `post-thread`.`author-id`
+                       LEFT JOIN `user-contact` AS `owner` ON `owner`.`uid` = `post-user`.`uid` AND `owner`.`cid` = `post-thread`.`owner-id`
+                       LEFT JOIN `contact` AS `ownercontact` ON `ownercontact`.`id` = `post-thread`.`owner-id`
+                       WHERE `item`.`visible` AND NOT `item`.`deleted` AND NOT `item`.`moderated`
                        AND (NOT `contact`.`readonly` AND NOT `contact`.`blocked` AND NOT `contact`.`pending`)
                        AND (`post-user`.`hidden` IS NULL OR NOT `post-user`.`hidden`)
                        AND (`author`.`blocked` IS NULL OR NOT `author`.`blocked`)
index 4c90ab8..e6d62c5 100644 (file)
@@ -1118,8 +1118,8 @@ function api_statuses_update($type)
                if ($throttle_day > 0) {
                        $datefrom = date(DateTimeFormat::MYSQL, time() - 24*60*60);
 
-                       $condition = ["`uid` = ? AND `wall` AND `received` > ?", api_user(), $datefrom];
-                       $posts_day = DBA::count('thread', $condition);
+                       $condition = ["`gravity` = ? AND `uid` = ? AND `wall` AND `received` > ?", GRAVITY_PARENT, api_user(), $datefrom];
+                       $posts_day = Post::count($condition);
 
                        if ($posts_day > $throttle_day) {
                                Logger::log('Daily posting limit reached for user '.api_user(), Logger::DEBUG);
@@ -1132,8 +1132,8 @@ function api_statuses_update($type)
                if ($throttle_week > 0) {
                        $datefrom = date(DateTimeFormat::MYSQL, time() - 24*60*60*7);
 
-                       $condition = ["`uid` = ? AND `wall` AND `received` > ?", api_user(), $datefrom];
-                       $posts_week = DBA::count('thread', $condition);
+                       $condition = ["`gravity` = ? AND `uid` = ? AND `wall` AND `received` > ?", GRAVITY_PARENT, api_user(), $datefrom];
+                       $posts_week = Post::count($condition);
 
                        if ($posts_week > $throttle_week) {
                                Logger::log('Weekly posting limit reached for user '.api_user(), Logger::DEBUG);
@@ -1146,8 +1146,8 @@ function api_statuses_update($type)
                if ($throttle_month > 0) {
                        $datefrom = date(DateTimeFormat::MYSQL, time() - 24*60*60*30);
 
-                       $condition = ["`uid` = ? AND `wall` AND `received` > ?", api_user(), $datefrom];
-                       $posts_month = DBA::count('thread', $condition);
+                       $condition = ["`gravity` = ? AND `uid` = ? AND `wall` AND `received` > ?", GRAVITY_PARENT, api_user(), $datefrom];
+                       $posts_month = Post::count($condition);
 
                        if ($posts_month > $throttle_month) {
                                Logger::log('Monthly posting limit reached for user '.api_user(), Logger::DEBUG);
index b7f840b..9fa34e5 100644 (file)
@@ -82,7 +82,7 @@ function notes_content(App $a, $update = false)
 
        $params = ['order' => ['created' => true],
                'limit' => [$pager->getStart(), $pager->getItemsPerPage()]];
-       $r = Post::selectThreadForUser(local_user(), ['uri-id'], $condition, $params);
+       $r = Post::selectForUser(local_user(), ['uri-id'], $condition, $params);
 
        $count = 0;
 
index 5041b7e..70530c4 100644 (file)
@@ -979,6 +979,10 @@ class Item
                        Post\Media::insertFromAttachment($item['uri-id'], $item['attach']);
                }
 
+               if ($item['gravity'] == GRAVITY_PARENT) {
+                       Post\Thread::insert($item['uri-id'], $item);
+               }
+
                if (!in_array($item['verb'], self::ACTIVITIES)) {
                        Post\Content::insert($item['uri-id'], $item);
                }
@@ -2203,9 +2207,9 @@ class Item
 
        public static function firstPostDate($uid, $wall = false)
        {
-               $condition = ['uid' => $uid, 'wall' => $wall, 'deleted' => false, 'visible' => true, 'moderated' => false];
+               $condition = ['gravity' => GRAVITY_PARENT, 'uid' => $uid, 'wall' => $wall, 'deleted' => false, 'visible' => true, 'moderated' => false];
                $params = ['order' => ['received' => false]];
-               $thread = DBA::selectFirst('thread', ['received'], $condition, $params);
+               $thread = Post::selectFirst(['received'], $condition, $params);
                if (DBA::isResult($thread)) {
                        return substr(DateTimeFormat::local($thread['received']), 0, 10);
                }
index 73742b3..d4aa9f1 100644 (file)
@@ -194,7 +194,7 @@ class Post
                                'parent-guid', 'parent-network', 'parent-author-id', 'parent-author-link', 'parent-author-name',
                                'parent-author-network', 'signed_text', 'language', 'raw-body'], Item::DISPLAY_FIELDLIST, Item::ITEM_FIELDLIST);
                        
-                       if ($view == 'post-thread-view') {
+                       if ($view != 'post-view') {
                                $selected = array_merge($selected, ['ignored', 'iid']);
                        }
                }
@@ -448,6 +448,18 @@ class Post
                        $affected = max($affected, DBA::affectedRows());
                }
 
+               $update_fields = DBStructure::getFieldsForTable('post-thread', $fields);
+               if (!empty($update_fields)) {
+                       $rows = DBA::selectToArray('post-view', ['uri-id'], $condition, ['group_by' => ['uri-id']]);
+                       $uriids = array_column($rows, 'uri-id');
+                       if (!DBA::update('post-thread', $update_fields, ['uri-id' => $uriids])) {
+                               DBA::rollback();
+                               Logger::notice('Updating post-thread failed', ['fields' => $update_fields, 'condition' => $condition]);
+                               return false;
+                       }
+                       $affected = max($affected, DBA::affectedRows());
+               }
+
                $update_fields = DBStructure::getFieldsForTable('post-thread-user', $fields);
                if (!empty($update_fields)) {
                        $rows = DBA::selectToArray('post-view', ['post-user-id'], $thread_condition);
diff --git a/src/Model/Post/Thread.php b/src/Model/Post/Thread.php
new file mode 100644 (file)
index 0000000..f5a5345
--- /dev/null
@@ -0,0 +1,97 @@
+<?php
+/**
+ * @copyright Copyright (C) 2020, Friendica
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Friendica\Model\Post;
+
+use \BadMethodCallException;
+use Friendica\Core\Protocol;
+use Friendica\Database\Database;
+use Friendica\Database\DBA;
+use Friendica\Database\DBStructure;
+use Friendica\Model\Post;
+
+class Thread
+{
+       /**
+        * Insert a new post-thread entry
+        *
+        * @param integer $uri_id
+        * @param array   $fields
+        * @return bool   success
+        * @throws \Exception
+        */
+       public static function insert(int $uri_id, array $data = [])
+       {
+               if (empty($uri_id)) {
+                       throw new BadMethodCallException('Empty URI_id');
+               }
+
+               $fields = DBStructure::getFieldsForTable('post-thread', $data);
+
+               // Additionally assign the key fields
+               $fields['uri-id'] = $uri_id;
+
+               return DBA::insert('post-thread', $fields, Database::INSERT_IGNORE);
+       }
+
+       /**
+        * Update a post-thread entry
+        *
+        * @param integer $uri_id
+        * @param array   $data
+        * @param bool    $insert_if_missing
+        * @return bool
+        * @throws \Exception
+        */
+       public static function update(int $uri_id, array $data = [], bool $insert_if_missing = false)
+       {
+               if (empty($uri_id)) {
+                       throw new BadMethodCallException('Empty URI_id');
+               }
+
+               $fields = DBStructure::getFieldsForTable('post-thread', $data);
+
+               // Remove the key fields
+               unset($fields['uri-id']);
+
+               if (empty($fields)) {
+                       return true;
+               }
+
+               return DBA::update('post-thread', $fields, ['uri-id' => $uri_id], $insert_if_missing ? true : []);
+       }
+
+       /**
+        * Delete a row from the post-thread table
+        *
+        * @param array        $conditions Field condition(s)
+        * @param array        $options
+        *                           - cascade: If true we delete records in other tables that depend on the one we're deleting through
+        *                           relations (default: true)
+        *
+        * @return boolean was the delete successful?
+        * @throws \Exception
+        */
+       public static function delete(array $conditions, array $options = [])
+       {
+               return DBA::delete('post-thread', $conditions, $options);
+       }
+}
index 2febbe5..026c31f 100644 (file)
@@ -336,7 +336,7 @@ class Community extends BaseModule
                        $condition[] = $item_id;
                } else {
                        if (local_user() && !empty($_REQUEST['no_sharer'])) {
-                               $condition[0] .= " AND NOT EXISTS (SELECT `uri-id` FROM `thread` AS t1 WHERE `t1`.`uri-id` = `thread`.`uri-id` AND `t1`.`uid` = ?)";
+                               $condition[0] .= " AND NOT EXISTS (SELECT `uri-id` FROM `post-user` WHERE `post-user`.`uri-id` = `post-thread-view`.`uri-id` AND `post-user`.`uid` = ?)";
                                $condition[] = local_user();
                        }
        
index 2c419c4..70a4f91 100644 (file)
@@ -52,12 +52,17 @@ class Expire
                        }
                        DBA::close($rows);
 
-                       // Normally we shouldn't have orphaned data at all.
-                       // If we do have some, then we have to check why.
-                       Logger::log('Deleting orphaned item content - start', Logger::DEBUG);
+                       Logger::info('Deleting orphaned post-content - start');
+                       /// @todo Replace "item with "post-user" in the future when "item" is removed
                        $condition = ["NOT EXISTS (SELECT `uri-id` FROM `item` WHERE `item`.`uri-id` = `post-content`.`uri-id`)"];
                        DBA::delete('post-content', $condition);
-                       Logger::log('Orphaned item content deleted: ' . DBA::affectedRows(), Logger::DEBUG);
+                       Logger::info('Orphaned post-content deleted', ['rows' => DBA::affectedRows()]);
+
+                       Logger::info('Deleting orphaned post-thread - start');
+                       /// @todo Replace "item with "post-user" in the future when "item" is removed
+                       $condition = ["NOT EXISTS (SELECT `uri-id` FROM `item` WHERE `item`.`uri-id` = `post-thread`.`uri-id`)"];
+                       DBA::delete('post-thread', $condition);
+                       Logger::info('Orphaned item content deleted', ['rows' => DBA::affectedRows()]);
 
                        // make this optional as it could have a performance impact on large sites
                        if (intval(DI::config()->get('system', 'optimize_items'))) {
index 34e43ec..010aef6 100644 (file)
@@ -47,6 +47,7 @@ class ExpirePosts
                if (!empty($expire_days)) {
                        do {
                                Logger::notice('Start deleting expired threads', ['expiry_days' => $expire_days]);
+                               /// @todo replace that query later
                                $ret = DBA::e("DELETE FROM `item-uri` WHERE `id` IN
                                        (SELECT `uri-id` FROM `thread`
                                        INNER JOIN `contact` ON `id` = `contact-id` AND NOT `notify_new_posts`
index c2a0719..f90abe3 100644 (file)
@@ -24,6 +24,7 @@ namespace Friendica\Worker;
 use Friendica\Core\Logger;
 use Friendica\Core\Protocol;
 use Friendica\Database\DBA;
+use Friendica\Database\DBStructure;
 use Friendica\Model\Photo;
 
 /**
@@ -37,8 +38,8 @@ class RemoveUnusedContacts
                        AND (NOT `network` IN (?, ?, ?, ?, ?, ?) OR (`archive` AND `success_update` < UTC_TIMESTAMP() - INTERVAL ? DAY))
                        AND NOT `id` IN (SELECT `author-id` FROM `item`) AND NOT `id` IN (SELECT `owner-id` FROM `item`)
                        AND NOT `id` IN (SELECT `causer-id` FROM `item`) AND NOT `id` IN (SELECT `cid` FROM `post-tag`)
-                       AND NOT `id` IN (SELECT `contact-id` FROM `item`) AND NOT `id` IN (SELECT `author-id` FROM `thread`)
-                       AND NOT `id` IN (SELECT `owner-id` FROM `thread`) AND NOT `id` IN (SELECT `contact-id` FROM `thread`)
+                       AND NOT `id` IN (SELECT `contact-id` FROM `item`) AND NOT `id` IN (SELECT `author-id` FROM `post-thread`)
+                       AND NOT `id` IN (SELECT `owner-id` FROM `post-thread`) AND NOT `id` IN (SELECT `causer-id` FROM `post-thread`)
                        AND NOT `id` IN (SELECT `contact-id` FROM `post-user`) AND NOT `id` IN (SELECT `cid` FROM `user-contact`) 
                        AND NOT `id` IN (SELECT `cid` FROM `event`) AND NOT `id` IN (SELECT `contact-id` FROM `group_member`)",
                        0, 0, Protocol::DFRN, Protocol::DIASPORA, Protocol::OSTATUS, Protocol::FEED, Protocol::MAIL, Protocol::ACTIVITYPUB, 365];
@@ -49,6 +50,10 @@ class RemoveUnusedContacts
                $contacts = DBA::select('contact', ['id', 'uid'], $condition);
                while ($contact = DBA::fetch($contacts)) {
                        if (Photo::delete(['uid' => $contact['uid'], 'contact-id' => $contact['id']])) {
+                               if (DBStructure::existsTable('thread')) {
+                                       DBA::delete('thread', ['owner-id' => $contact['id']]);
+                                       DBA::delete('thread', ['author-id' => $contact['id']]);
+                               }
                                DBA::delete('contact', ['id' => $contact['id']]);
                                if ((++$count % 1000) == 0) {
                                        Logger::notice('In removal', ['count' => $count, 'total' => $total]);
index 6b8aba3..370479b 100644 (file)
@@ -55,7 +55,7 @@
 use Friendica\Database\DBA;
 
 if (!defined('DB_UPDATE_VERSION')) {
-       define('DB_UPDATE_VERSION', 1397);
+       define('DB_UPDATE_VERSION', 1398);
 }
 
 return [
@@ -1181,6 +1181,29 @@ return [
                        "cid" => ["cid"]
                ]
        ],
+       "post-thread" => [
+               "comment" => "Thread related data",
+               "fields" => [
+                       "uri-id" => ["type" => "int unsigned", "not null" => "1", "primary" => "1", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the item uri"],
+                       "owner-id" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "foreign" => ["contact" => "id", "on delete" => "restrict"], "comment" => "Item owner"],
+                       "author-id" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "foreign" => ["contact" => "id", "on delete" => "restrict"], "comment" => "Item author"],
+                       "causer-id" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "foreign" => ["contact" => "id", "on delete" => "restrict"], "comment" => "Link to the contact table with uid=0 of the contact that caused the item creation"],
+                       "network" => ["type" => "char(4)", "not null" => "1", "default" => "", "comment" => ""],
+                       "created" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => ""],
+                       "received" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => ""],
+                       "changed" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "Date that something in the conversation changed, indicating clients should fetch the conversation again"],
+                       "commented" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => ""]
+               ],
+               "indexes" => [
+                       "PRIMARY" => ["uri-id"],
+                       "owner-id" => ["owner-id"],
+                       "author-id" => ["author-id"],
+                       "causer-id" => ["causer-id"],
+                       "received" => ["received"],
+                       "commented" => ["commented"],
+                       "changed" => ["changed"]
+               ]
+       ],
        "post-thread-user" => [
                "comment" => "Thread related data per user",
                "fields" => [
@@ -1190,6 +1213,7 @@ return [
                        "starred" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
                        "ignored" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "Ignore updates for this thread"],
                        "wall" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "This item was posted to the wall of uid"],
+                       "mention" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
                        "pubmail" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
                        "forum_mode" => ["type" => "tinyint unsigned", "not null" => "1", "default" => "0", "comment" => ""]
                ],
index 088e426..98fe5fb 100644 (file)
        "post-thread-view" => [
                "fields" => [
                        "id" => ["item", "id"],
-                       "iid" => ["thread", "iid"],
+                       "iid" => ["item", "id"],
                        "item_id" => ["item", "id"],
-                       "uid" => ["thread", "uid"],
+                       "uid" => ["post-thread-user", "uid"],
                        "parent" => ["item", "parent"],
                        "uri" => ["item", "uri"],
-                       "uri-id" => ["item", "uri-id"],
+                       "uri-id" => ["post-thread", "uri-id"],
                        "parent-uri" => ["item", "parent-uri"],
                        "parent-uri-id" => ["item", "parent-uri-id"],
                        "thr-parent" => ["item", "thr-parent"],
                        "thr-parent-id" => ["item", "thr-parent-id"],
                        "guid" => ["item", "guid"],
                        "type" => ["item", "type"],
-                       "wall" => ["thread", "wall"],
+                       "wall" => ["post-thread-user", "wall"],
                        "gravity" => ["item", "gravity"],
                        "extid" => ["item", "extid"],
-                       "created" => ["thread", "created"],
+                       "created" => ["post-thread", "created"],
                        "edited" => ["item", "edited"],
-                       "commented" => ["thread", "commented"],
-                       "received" => ["thread", "received"],
-                       "changed" => ["thread", "changed"],
-                       "post-type" => ["thread", "post-type"],
-                       "private" => ["thread", "private"],
-                       "pubmail" => ["thread", "pubmail"],
-                       "moderated" => ["thread", "moderated"],
-                       "ignored" => ["thread", "ignored"],
-                       "visible" => ["thread", "visible"],
-                       "starred" => ["thread", "starred"],
+                       "commented" => ["post-thread", "commented"],
+                       "received" => ["post-thread", "received"],
+                       "changed" => ["post-thread", "changed"],
+                       "post-type" => ["item", "post-type"],
+                       "private" => ["item", "private"],
+                       "pubmail" => ["post-thread-user", "pubmail"],
+                       "moderated" => ["item", "moderated"],
+                       "ignored" => ["post-thread-user", "ignored"],
+                       "visible" => ["item", "visible"],
+                       "starred" => ["post-thread-user", "starred"],
                        "bookmark" => ["item", "bookmark"],
-                       "unseen" => ["item", "unseen"],
-                       "deleted" => ["thread", "deleted"],
-                       "origin" => ["thread", "origin"],
-                       "forum_mode" => ["thread", "forum_mode"],
-                       "mention" => ["thread", "mention"],
+                       "unseen" => ["post-user", "unseen"],
+                       "deleted" => ["item", "deleted"],
+                       "origin" => ["post-user", "origin"],
+                       "forum_mode" => ["post-thread-user", "forum_mode"],
+                       "mention" => ["item", "mention"],
                        "global" => ["item", "global"],
-                       "network" => ["thread", "network"],
+                       "network" => ["post-thread", "network"],
                        "vid" => ["item", "vid"],
-                       "psid" => ["item", "psid"],
+                       "psid" => ["post-user", "psid"],
                        "verb" => "IF (`item`.`vid` IS NULL, '', `verb`.`name`)",
                        "title" => ["post-content", "title"],
                        "content-warning" => ["post-content", "content-warning"],
                        "target-type" => ["post-content", "target-type"],
                        "target" => ["post-content", "target"],
                        "resource-id" => ["post-content", "resource-id"],
-                       "contact-id" => ["thread", "contact-id"],
+                       "contact-id" => ["post-user", "contact-id"],
                        "contact-link" => ["contact", "url"],
                        "contact-addr" => ["contact", "addr"],
                        "contact-name" => ["contact", "name"],
                        "avatar-date" => ["contact", "avatar-date"],
                        "thumb" => ["contact", "thumb"],
                        "dfrn-id" => ["contact", "dfrn-id"],
-                       "author-id" => ["thread", "author-id"],
+                       "author-id" => ["post-thread", "author-id"],
                        "author-link" => ["author", "url"],
                        "author-addr" => ["author", "addr"],
                        "author-name" => "IF (`contact`.`url` = `author`.`url` AND `contact`.`name` != '', `contact`.`name`, `author`.`name`)",
                        "author-network" => ["author", "network"],
                        "author-blocked" => ["author", "blocked"],
                        "author-hidden" => ["author", "hidden"],
-                       "owner-id" => ["thread", "owner-id"],
+                       "owner-id" => ["post-thread", "owner-id"],
                        "owner-link" => ["owner", "url"],
                        "owner-addr" => ["owner", "addr"],
                        "owner-name" => "IF (`contact`.`url` = `owner`.`url` AND `contact`.`name` != '', `contact`.`name`, `owner`.`name`)",
                        "delivery_queue_count" => ["post-delivery-data", "queue_count"],
                        "delivery_queue_done" => ["post-delivery-data", "queue_done"],
                        "delivery_queue_failed" => ["post-delivery-data", "queue_failed"],
-                       "allow_cid" => "IF (`item`.`psid` IS NULL, '', `permissionset`.`allow_cid`)",
-                       "allow_gid" => "IF (`item`.`psid` IS NULL, '', `permissionset`.`allow_gid`)",
-                       "deny_cid" => "IF (`item`.`psid` IS NULL, '', `permissionset`.`deny_cid`)",
-                       "deny_gid" => "IF (`item`.`psid` IS NULL, '', `permissionset`.`deny_gid`)",
+                       "allow_cid" => "IF (`post-user`.`psid` IS NULL, '', `permissionset`.`allow_cid`)",
+                       "allow_gid" => "IF (`post-user`.`psid` IS NULL, '', `permissionset`.`allow_gid`)",
+                       "deny_cid" => "IF (`post-user`.`psid` IS NULL, '', `permissionset`.`deny_cid`)",
+                       "deny_gid" => "IF (`post-user`.`psid` IS NULL, '', `permissionset`.`deny_gid`)",
                        "event-id" => ["item", "event-id"],
                        "event-created" => ["event", "created"],
                        "event-edited" => ["event", "edited"],
                        "parent-author-name" => ["parent-item-author", "name"],
                        "parent-author-network" => ["parent-item-author", "network"], 
                ],
-               "query" => "FROM `thread`
-                       STRAIGHT_JOIN `item` ON `item`.`id` = `thread`.`iid`
-                       STRAIGHT_JOIN `contact` ON `contact`.`id` = `thread`.`contact-id`
-                       STRAIGHT_JOIN `contact` AS `author` ON `author`.`id` = `thread`.`author-id`
-                       STRAIGHT_JOIN `contact` AS `owner` ON `owner`.`id` = `thread`.`owner-id`
-                       STRAIGHT_JOIN `contact` AS `causer` ON `causer`.`id` = `item`.`causer-id`
+               "query" => "FROM `post-thread`
+                       STRAIGHT_JOIN `post-thread-user` ON `post-thread-user`.`uri-id` = `post-thread`.`uri-id`
+                       STRAIGHT_JOIN `post-user` ON `post-user`.`uri-id` = `post-thread`.`uri-id`
+                       STRAIGHT_JOIN `item` ON `item`.`uri-id` = `post-thread`.`uri-id` AND `item`.`uid` = `post-thread-user`.`uid`
+                       STRAIGHT_JOIN `contact` ON `contact`.`id` = `post-user`.`contact-id`
+                       STRAIGHT_JOIN `contact` AS `author` ON `author`.`id` = `post-thread`.`author-id`
+                       STRAIGHT_JOIN `contact` AS `owner` ON `owner`.`id` = `post-thread`.`owner-id`
+                       STRAIGHT_JOIN `contact` AS `causer` ON `causer`.`id` = `post-thread`.`causer-id`
                        LEFT JOIN `verb` ON `verb`.`id` = `item`.`vid`
                        LEFT JOIN `event` ON `event`.`id` = `item`.`event-id`
-                       LEFT JOIN `diaspora-interaction` ON `diaspora-interaction`.`uri-id` = `thread`.`uri-id`
-                       LEFT JOIN `post-content` ON `post-content`.`uri-id` = `thread`.`uri-id`
-                       LEFT JOIN `post-delivery-data` ON `post-delivery-data`.`uri-id` = `thread`.`uri-id` AND `thread`.`origin`
-                       LEFT JOIN `permissionset` ON `permissionset`.`id` = `item`.`psid`
+                       LEFT JOIN `diaspora-interaction` ON `diaspora-interaction`.`uri-id` = `post-thread`.`uri-id`
+                       LEFT JOIN `post-content` ON `post-content`.`uri-id` = `post-thread`.`uri-id`
+                       LEFT JOIN `post-delivery-data` ON `post-delivery-data`.`uri-id` = `post-thread`.`uri-id` AND `post-user`.`origin`
+                       LEFT JOIN `permissionset` ON `permissionset`.`id` = `post-user`.`psid`
                        STRAIGHT_JOIN `item` AS `parent-item` ON `parent-item`.`id` = `item`.`parent`
                        STRAIGHT_JOIN `contact` AS `parent-item-author` ON `parent-item-author`.`id` = `parent-item`.`author-id`"
        ],
                        "contact-type" => ["ownercontact", "contact-type"],
                ],
                "query" => "FROM `item`
-                       INNER JOIN `thread` ON `thread`.`iid` = `item`.`parent`
-                       STRAIGHT_JOIN `contact` ON `contact`.`id` = `thread`.`contact-id`
-                       LEFT JOIN `post-user` ON `post-user`.`uri-id` = `item`.`uri-id` AND `post-user`.`uid` = `thread`.`uid`
-                       LEFT JOIN `user-contact` AS `author` ON `author`.`uid` = `thread`.`uid` AND `author`.`cid` = `thread`.`author-id`
-                       LEFT JOIN `user-contact` AS `owner` ON `owner`.`uid` = `thread`.`uid` AND `owner`.`cid` = `thread`.`owner-id`
-                       LEFT JOIN `contact` AS `ownercontact` ON `ownercontact`.`id` = `thread`.`owner-id`
-                       WHERE `thread`.`visible` AND NOT `thread`.`deleted` AND NOT `thread`.`moderated`
+                       INNER JOIN `item` AS `parent-item` ON `parent-item`.`id` = `item`.`parent`
+                       STRAIGHT_JOIN `contact` ON `contact`.`id` = `parent-item`.`contact-id`
+                       LEFT JOIN `post-user` ON `post-user`.`uri-id` = `item`.`uri-id` AND `post-user`.`uid` = `parent-item`.`uid`
+                       LEFT JOIN `user-contact` AS `author` ON `author`.`uid` = `parent-item`.`uid` AND `author`.`cid` = `parent-item`.`author-id`
+                       LEFT JOIN `user-contact` AS `owner` ON `owner`.`uid` = `parent-item`.`uid` AND `owner`.`cid` = `parent-item`.`owner-id`
+                       LEFT JOIN `contact` AS `ownercontact` ON `ownercontact`.`id` = `parent-item`.`owner-id`
+                       WHERE `parent-item`.`visible` AND NOT `parent-item`.`deleted` AND NOT `parent-item`.`moderated`
                        AND (NOT `contact`.`readonly` AND NOT `contact`.`blocked` AND NOT `contact`.`pending`)
                        AND (`post-user`.`hidden` IS NULL OR NOT `post-user`.`hidden`)
                        AND (`author`.`blocked` IS NULL OR NOT `author`.`blocked`)
        ],
        "network-thread-view" => [
                "fields" => [
-                       "uri-id" => ["item", "uri-id"],
+                       "uri-id" => ["post-thread", "uri-id"],
                        "uri" => ["item", "uri"],
                        "parent-uri-id" => ["item", "parent-uri-id"],
-                       "parent" => ["thread", "iid"],
-                       "received" => ["thread", "received"],
-                       "commented" => ["thread", "commented"],
-                       "created" => ["thread", "created"],
-                       "uid" => ["thread", "uid"],
-                       "starred" => ["thread", "starred"],
-                       "mention" => ["thread", "mention"],
-                       "network" => ["thread", "network"],
-                       "contact-id" => ["thread", "contact-id"],
+                       "parent" => ["item", "id"],
+                       "received" => ["post-thread", "received"],
+                       "commented" => ["post-thread", "commented"],
+                       "created" => ["post-thread", "created"],
+                       "uid" => ["post-thread-user", "uid"],
+                       "starred" => ["post-thread-user", "starred"],
+                       "mention" => ["post-thread-user", "mention"],
+                       "network" => ["post-thread", "network"],
+                       "contact-id" => ["post-user", "contact-id"],
                        "contact-type" => ["ownercontact", "contact-type"],
                ],
-               "query" => "FROM `thread`
-                       STRAIGHT_JOIN `contact` ON `contact`.`id` = `thread`.`contact-id`
-                       STRAIGHT_JOIN `item` ON `item`.`id` = `thread`.`iid`
-                       LEFT JOIN `post-user` ON `post-user`.`uri-id` = `item`.`uri-id` AND `post-user`.`uid` = `thread`.`uid`
-                       LEFT JOIN `user-contact` AS `author` ON `author`.`uid` = `thread`.`uid` AND `author`.`cid` = `thread`.`author-id`
-                       LEFT JOIN `user-contact` AS `owner` ON `owner`.`uid` = `thread`.`uid` AND `owner`.`cid` = `thread`.`owner-id`
-                       LEFT JOIN `contact` AS `ownercontact` ON `ownercontact`.`id` = `thread`.`owner-id`
-                       WHERE `thread`.`visible` AND NOT `thread`.`deleted` AND NOT `thread`.`moderated`
+               "query" => "FROM `post-thread`
+                       STRAIGHT_JOIN `post-thread-user` ON `post-thread-user`.`uri-id` = `post-thread`.`uri-id`
+                       STRAIGHT_JOIN `post-user` ON `post-user`.`uri-id` = `post-thread`.`uri-id` AND `post-user`.`uid` = `post-thread-user`.`uid`
+                       STRAIGHT_JOIN `item` ON `item`.`uri-id` = `post-thread`.`uri-id` AND `item`.`uid` = `post-thread-user`.`uid`
+                       STRAIGHT_JOIN `contact` ON `contact`.`id` = `post-user`.`contact-id`
+                       LEFT JOIN `user-contact` AS `author` ON `author`.`uid` = `post-user`.`uid` AND `author`.`cid` = `post-thread`.`author-id`
+                       LEFT JOIN `user-contact` AS `owner` ON `owner`.`uid` = `post-user`.`uid` AND `owner`.`cid` = `post-thread`.`owner-id`
+                       LEFT JOIN `contact` AS `ownercontact` ON `ownercontact`.`id` = `post-thread`.`owner-id`
+                       WHERE `item`.`visible` AND NOT `item`.`deleted` AND NOT `item`.`moderated`
                        AND (NOT `contact`.`readonly` AND NOT `contact`.`blocked` AND NOT `contact`.`pending`)
                        AND (`post-user`.`hidden` IS NULL OR NOT `post-user`.`hidden`)
                        AND (`author`.`blocked` IS NULL OR NOT `author`.`blocked`)
index 9402906..9f85926 100644 (file)
@@ -295,7 +295,7 @@ function update_1349()
 
 function update_1351()
 {
-       if (!DBA::e("UPDATE `thread` INNER JOIN `item` ON `thread`.`iid` = `item`.`id` SET `thread`.`uri-id` = `item`.`uri-id`")) {
+       if (DBStructure::existsTable('thread') && !DBA::e("UPDATE `thread` INNER JOIN `item` ON `thread`.`iid` = `item`.`id` SET `thread`.`uri-id` = `item`.`uri-id`")) {
                return Update::FAILED;
        }
 
@@ -519,7 +519,7 @@ function pre_update_1365()
                return Update::FAILED;
        }
 
-       if (!DBA::e("DELETE FROM `thread` WHERE NOT `iid` IN (SELECT `id` FROM `item`)")) {
+       if (DBStructure::existsTable('thread') && !DBA::e("DELETE FROM `thread` WHERE NOT `iid` IN (SELECT `id` FROM `item`)")) {
                return Update::FAILED;
        }
 
@@ -548,7 +548,7 @@ function pre_update_1376()
                return Update::FAILED;
        }
 
-       if (!DBA::e("DELETE FROM `thread` WHERE NOT `uid` IN (SELECT `uid` FROM `user`)")) {
+       if (DBStructure::existsTable('thread') && !DBA::e("DELETE FROM `thread` WHERE NOT `uid` IN (SELECT `uid` FROM `user`)")) {
                return Update::FAILED;
        }
 
@@ -589,15 +589,15 @@ function pre_update_1377()
                return Update::FAILED;
        }
 
-       if (!DBA::e("DELETE FROM `thread` WHERE NOT `author-id` IN (SELECT `id` FROM `contact`)")) {
+       if (DBStructure::existsTable('thread') && !DBA::e("DELETE FROM `thread` WHERE NOT `author-id` IN (SELECT `id` FROM `contact`)")) {
                return Update::FAILED;
        }
 
-       if (!DBA::e("DELETE FROM `thread` WHERE NOT `owner-id` IN (SELECT `id` FROM `contact`)")) {
+       if (DBStructure::existsTable('thread') && !DBA::e("DELETE FROM `thread` WHERE NOT `owner-id` IN (SELECT `id` FROM `contact`)")) {
                return Update::FAILED;
        }
 
-       if (!DBA::e("UPDATE `thread` SET `contact-id` = `owner-id` WHERE NOT `contact-id` IN (SELECT `id` FROM `contact`)")) {
+       if (DBStructure::existsTable('thread') && !DBA::e("UPDATE `thread` SET `contact-id` = `owner-id` WHERE NOT `contact-id` IN (SELECT `id` FROM `contact`)")) {
                return Update::FAILED;
        }
 
@@ -735,3 +735,27 @@ function update_1397()
 
        return Update::SUCCESS;
 }
+
+function update_1398()
+{
+       if (!DBStructure::existsTable('thread')) {
+               return Update::SUCCESS;
+       }
+
+       if (!DBA::e("INSERT IGNORE INTO `post-thread` (`uri-id`, `owner-id`, `author-id`, `network`, `created`, `received`, `changed`, `commented`)
+               SELECT `uri-id`, `owner-id`, `author-id`, `network`, `created`, `received`, `changed`, `commented` FROM `thread`")) {
+                       return Update::FAILED;
+       }
+
+       if (!DBStructure::existsTable('thread')) {
+               return Update::SUCCESS;
+       }
+
+       if (!DBA::e("UPDATE `post-thread-user` INNER JOIN `thread` ON `thread`.`uid` = `post-thread-user`.`uid` AND `thread`.`uri-id` = `post-thread-user`.`uri-id`
+               SET `post-thread-user`.`mention` = `thread`.`mention`")) {
+                       return Update::FAILED;
+       }
+
+       return Update::SUCCESS;
+
+}
\ No newline at end of file