Performance improvements when displaying local posts

This commit is contained in:
Michael 2024-04-17 19:16:47 +00:00
parent bae1f63424
commit c82a1ed467
16 changed files with 1101 additions and 28 deletions

View file

@ -1,6 +1,6 @@
-- ------------------------------------------
-- Friendica 2024.06-dev (Yellow Archangel)
-- DB_UPDATE_VERSION 1559
-- DB_UPDATE_VERSION 1560
-- ------------------------------------------
@ -1439,6 +1439,36 @@ CREATE TABLE IF NOT EXISTS `post-media` (
FOREIGN KEY (`media-uri-id`) REFERENCES `item-uri` (`id`) ON UPDATE RESTRICT ON DELETE CASCADE
) DEFAULT COLLATE utf8mb4_general_ci COMMENT='Attached media';
--
-- TABLE post-origin
--
CREATE TABLE IF NOT EXISTS `post-origin` (
`id` int unsigned NOT NULL,
`uri-id` int unsigned NOT NULL COMMENT 'Id of the item-uri table entry that contains the item uri',
`uid` mediumint unsigned NOT NULL COMMENT 'Owner id which owns this copy of the item',
`parent-uri-id` int unsigned COMMENT 'Id of the item-uri table that contains the parent uri',
`thr-parent-id` int unsigned COMMENT 'Id of the item-uri table that contains the thread parent uri',
`created` datetime NOT NULL DEFAULT '0001-01-01 00:00:00' COMMENT 'Creation timestamp.',
`received` datetime NOT NULL DEFAULT '0001-01-01 00:00:00' COMMENT 'datetime',
`gravity` tinyint unsigned NOT NULL DEFAULT 0 COMMENT '',
`vid` smallint unsigned COMMENT 'Id of the verb table entry that contains the activity verbs',
`private` tinyint unsigned NOT NULL DEFAULT 0 COMMENT '0=public, 1=private, 2=unlisted',
`wall` boolean NOT NULL DEFAULT '0' COMMENT 'This item was posted to the wall of uid',
PRIMARY KEY(`id`),
UNIQUE INDEX `uid_uri-id` (`uid`,`uri-id`),
INDEX `uri-id` (`uri-id`),
INDEX `parent-uri-id` (`parent-uri-id`),
INDEX `thr-parent-id` (`thr-parent-id`),
INDEX `vid` (`vid`),
INDEX `parent-uri-id_uid` (`parent-uri-id`,`uid`),
INDEX `uid_wall_received` (`uid`,`wall`,`received`),
FOREIGN KEY (`uri-id`) REFERENCES `item-uri` (`id`) ON UPDATE RESTRICT ON DELETE CASCADE,
FOREIGN KEY (`uid`) REFERENCES `user` (`uid`) ON UPDATE RESTRICT ON DELETE CASCADE,
FOREIGN KEY (`parent-uri-id`) REFERENCES `item-uri` (`id`) ON UPDATE RESTRICT ON DELETE CASCADE,
FOREIGN KEY (`thr-parent-id`) REFERENCES `item-uri` (`id`) ON UPDATE RESTRICT ON DELETE CASCADE,
FOREIGN KEY (`vid`) REFERENCES `verb` (`id`) ON UPDATE RESTRICT ON DELETE RESTRICT
) DEFAULT COLLATE utf8mb4_general_ci COMMENT='Posts from local users';
--
-- TABLE post-question
--
@ -2112,6 +2142,52 @@ CREATE VIEW `post-timeline-view` AS SELECT
STRAIGHT_JOIN `contact` AS `owner` ON `owner`.`id` = `post-user`.`owner-id`
LEFT JOIN `contact` AS `causer` ON `causer`.`id` = `post-user`.`causer-id`;
--
-- VIEW post-timeline-origin-view
--
DROP VIEW IF EXISTS `post-timeline-origin-view`;
CREATE VIEW `post-timeline-origin-view` AS SELECT
`post-origin`.`uid` AS `uid`,
`post-origin`.`uri-id` AS `uri-id`,
`post-origin`.`gravity` AS `gravity`,
`post-origin`.`created` AS `created`,
`post-user`.`edited` AS `edited`,
`post-thread-user`.`commented` AS `commented`,
`post-origin`.`received` AS `received`,
`post-thread-user`.`changed` AS `changed`,
`post-origin`.`private` AS `private`,
`post-user`.`visible` AS `visible`,
`post-user`.`deleted` AS `deleted`,
true AS `origin`,
`post-user`.`global` AS `global`,
`post-user`.`network` AS `network`,
`post-user`.`protocol` AS `protocol`,
`post-origin`.`vid` AS `vid`,
`post-user`.`contact-id` AS `contact-id`,
`contact`.`blocked` AS `contact-blocked`,
`contact`.`readonly` AS `contact-readonly`,
`contact`.`pending` AS `contact-pending`,
`contact`.`rel` AS `contact-rel`,
`contact`.`uid` AS `contact-uid`,
`contact`.`self` AS `self`,
`post-user`.`author-id` AS `author-id`,
`author`.`blocked` AS `author-blocked`,
`author`.`hidden` AS `author-hidden`,
`author`.`gsid` AS `author-gsid`,
`post-user`.`owner-id` AS `owner-id`,
`owner`.`blocked` AS `owner-blocked`,
`owner`.`gsid` AS `owner-gsid`,
`post-user`.`causer-id` AS `causer-id`,
`causer`.`blocked` AS `causer-blocked`,
`causer`.`gsid` AS `causer-gsid`
FROM `post-origin`
INNER JOIN `post-user` ON `post-user`.`id` = `post-origin`.`id`
LEFT JOIN `post-thread-user` ON `post-thread-user`.`uri-id` = `post-origin`.`parent-uri-id` AND `post-thread-user`.`uid` = `post-origin`.`uid`
STRAIGHT_JOIN `contact` ON `contact`.`id` = `post-user`.`contact-id`
STRAIGHT_JOIN `contact` AS `author` ON `author`.`id` = `post-user`.`author-id`
STRAIGHT_JOIN `contact` AS `owner` ON `owner`.`id` = `post-user`.`owner-id`
LEFT JOIN `contact` AS `causer` ON `causer`.`id` = `post-user`.`causer-id`;
--
-- VIEW post-searchindex-user-view
--
@ -2144,6 +2220,380 @@ CREATE VIEW `post-searchindex-user-view` AS SELECT
AND NOT EXISTS(SELECT `cid` FROM `user-contact` WHERE `uid` = `post-thread-user`.`uid` AND `cid` IN (`authorcontact`.`id`, `ownercontact`.`id`) AND (`blocked` OR `ignored`))
AND NOT EXISTS(SELECT `gsid` FROM `user-gserver` WHERE `uid` = `post-thread-user`.`uid` AND `gsid` IN (`authorcontact`.`gsid`, `ownercontact`.`gsid`) AND `ignored`);
--
-- VIEW post-origin-view
--
DROP VIEW IF EXISTS `post-origin-view`;
CREATE VIEW `post-origin-view` AS SELECT
`post-origin`.`id` AS `id`,
`post-origin`.`id` AS `post-user-id`,
`post-origin`.`uid` AS `uid`,
`post-thread-user`.`post-user-id` AS `parent`,
`item-uri`.`uri` AS `uri`,
`post-origin`.`uri-id` AS `uri-id`,
`parent-item-uri`.`uri` AS `parent-uri`,
`post-origin`.`parent-uri-id` AS `parent-uri-id`,
`thr-parent-item-uri`.`uri` AS `thr-parent`,
`post-origin`.`thr-parent-id` AS `thr-parent-id`,
`conversation-item-uri`.`uri` AS `conversation`,
`post-thread-user`.`conversation-id` AS `conversation-id`,
`quote-item-uri`.`uri` AS `quote-uri`,
`post-content`.`quote-uri-id` AS `quote-uri-id`,
`item-uri`.`guid` AS `guid`,
`post-origin`.`wall` AS `wall`,
`post-origin`.`gravity` AS `gravity`,
`external-item-uri`.`uri` AS `extid`,
`post-user`.`external-id` AS `external-id`,
`post-origin`.`created` AS `created`,
`post-user`.`edited` AS `edited`,
`post-thread-user`.`commented` AS `commented`,
`post-origin`.`received` AS `received`,
`post-thread-user`.`changed` AS `changed`,
`post-user`.`post-type` AS `post-type`,
`post-user`.`post-reason` AS `post-reason`,
`post-origin`.`private` AS `private`,
`post-thread-user`.`pubmail` AS `pubmail`,
`post-user`.`visible` AS `visible`,
`post-thread-user`.`starred` AS `starred`,
`post-user`.`unseen` AS `unseen`,
`post-user`.`deleted` AS `deleted`,
true AS `origin`,
`post-thread-user`.`origin` AS `parent-origin`,
`post-thread-user`.`mention` AS `mention`,
`post-user`.`global` AS `global`,
EXISTS(SELECT `type` FROM `post-collection` WHERE `type` = 0 AND `uri-id` = `post-origin`.`uri-id`) AS `featured`,
`post-user`.`network` AS `network`,
`post-user`.`protocol` AS `protocol`,
`post-origin`.`vid` AS `vid`,
`post-user`.`psid` AS `psid`,
IF (`post-origin`.`vid` IS NULL, '', `verb`.`name`) AS `verb`,
`post-content`.`title` AS `title`,
`post-content`.`content-warning` AS `content-warning`,
`post-content`.`raw-body` AS `raw-body`,
IFNULL (`post-content`.`body`, '') AS `body`,
`post-content`.`rendered-hash` AS `rendered-hash`,
`post-content`.`rendered-html` AS `rendered-html`,
`post-content`.`language` AS `language`,
`post-content`.`plink` AS `plink`,
`post-content`.`location` AS `location`,
`post-content`.`coord` AS `coord`,
`post-content`.`sensitive` AS `sensitive`,
`post-user`.`restrictions` AS `restrictions`,
`post-content`.`app` AS `app`,
`post-content`.`object-type` AS `object-type`,
`post-content`.`object` AS `object`,
`post-content`.`target-type` AS `target-type`,
`post-content`.`target` AS `target`,
`post-content`.`resource-id` AS `resource-id`,
`post-user`.`contact-id` AS `contact-id`,
`contact`.`uri-id` AS `contact-uri-id`,
`contact`.`url` AS `contact-link`,
`contact`.`addr` AS `contact-addr`,
`contact`.`name` AS `contact-name`,
`contact`.`nick` AS `contact-nick`,
`contact`.`thumb` AS `contact-avatar`,
`contact`.`network` AS `contact-network`,
`contact`.`blocked` AS `contact-blocked`,
`contact`.`hidden` AS `contact-hidden`,
`contact`.`readonly` AS `contact-readonly`,
`contact`.`archive` AS `contact-archive`,
`contact`.`pending` AS `contact-pending`,
`contact`.`rel` AS `contact-rel`,
`contact`.`uid` AS `contact-uid`,
`contact`.`contact-type` AS `contact-contact-type`,
IF (`post-user`.`network` IN ('apub', 'dfrn', 'dspr', 'stat'), true, `contact`.`writable`) AS `writable`,
`contact`.`self` AS `self`,
`contact`.`id` AS `cid`,
`contact`.`alias` AS `alias`,
`contact`.`photo` AS `photo`,
`contact`.`name-date` AS `name-date`,
`contact`.`uri-date` AS `uri-date`,
`contact`.`avatar-date` AS `avatar-date`,
`contact`.`thumb` AS `thumb`,
`post-user`.`author-id` AS `author-id`,
`author`.`uri-id` AS `author-uri-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`,
`author`.`nick` AS `author-nick`,
`author`.`alias` AS `author-alias`,
IF (`contact`.`url` = `author`.`url` AND `contact`.`thumb` != '', `contact`.`thumb`, `author`.`thumb`) AS `author-avatar`,
`author`.`network` AS `author-network`,
`author`.`blocked` AS `author-blocked`,
`author`.`hidden` AS `author-hidden`,
`author`.`updated` AS `author-updated`,
`author`.`contact-type` AS `author-contact-type`,
`author`.`gsid` AS `author-gsid`,
`author`.`baseurl` AS `author-baseurl`,
`post-user`.`owner-id` AS `owner-id`,
`owner`.`uri-id` AS `owner-uri-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`,
`owner`.`nick` AS `owner-nick`,
`owner`.`alias` AS `owner-alias`,
IF (`contact`.`url` = `owner`.`url` AND `contact`.`thumb` != '', `contact`.`thumb`, `owner`.`thumb`) AS `owner-avatar`,
`owner`.`network` AS `owner-network`,
`owner`.`blocked` AS `owner-blocked`,
`owner`.`hidden` AS `owner-hidden`,
`owner`.`updated` AS `owner-updated`,
`owner`.`gsid` AS `owner-gsid`,
`owner`.`contact-type` AS `owner-contact-type`,
`post-user`.`causer-id` AS `causer-id`,
`causer`.`uri-id` AS `causer-uri-id`,
`causer`.`url` AS `causer-link`,
`causer`.`addr` AS `causer-addr`,
`causer`.`name` AS `causer-name`,
`causer`.`nick` AS `causer-nick`,
`causer`.`alias` AS `causer-alias`,
`causer`.`thumb` AS `causer-avatar`,
`causer`.`network` AS `causer-network`,
`causer`.`blocked` AS `causer-blocked`,
`causer`.`hidden` AS `causer-hidden`,
`causer`.`gsid` AS `causer-gsid`,
`causer`.`contact-type` AS `causer-contact-type`,
`post-delivery-data`.`postopts` AS `postopts`,
`post-delivery-data`.`inform` AS `inform`,
`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 (`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`,
`post-user`.`event-id` AS `event-id`,
`event`.`created` AS `event-created`,
`event`.`edited` AS `event-edited`,
`event`.`start` AS `event-start`,
`event`.`finish` AS `event-finish`,
`event`.`summary` AS `event-summary`,
`event`.`desc` AS `event-desc`,
`event`.`location` AS `event-location`,
`event`.`type` AS `event-type`,
`event`.`nofinish` AS `event-nofinish`,
`event`.`ignore` AS `event-ignore`,
`post-question`.`id` AS `question-id`,
`post-question`.`multiple` AS `question-multiple`,
`post-question`.`voters` AS `question-voters`,
`post-question`.`end-time` AS `question-end-time`,
EXISTS(SELECT `uri-id` FROM `post-category` WHERE `post-category`.`uri-id` = `post-origin`.`uri-id` AND `post-category`.`uid` = `post-origin`.`uid`) AS `has-categories`,
EXISTS(SELECT `id` FROM `post-media` WHERE `post-media`.`uri-id` = `post-origin`.`uri-id`) AS `has-media`,
`diaspora-interaction`.`interaction` AS `signed_text`,
`parent-item-uri`.`guid` AS `parent-guid`,
`post-thread-user`.`network` AS `parent-network`,
`post-thread-user`.`author-id` AS `parent-author-id`,
`parent-post-author`.`url` AS `parent-author-link`,
`parent-post-author`.`name` AS `parent-author-name`,
`parent-post-author`.`nick` AS `parent-author-nick`,
`parent-post-author`.`network` AS `parent-author-network`
FROM `post-origin`
INNER JOIN `post-user` ON `post-user`.`id` = `post-origin`.`id`
INNER JOIN `post-thread-user` ON `post-thread-user`.`uri-id` = `post-origin`.`parent-uri-id` AND `post-thread-user`.`uid` = `post-origin`.`uid`
STRAIGHT_JOIN `contact` ON `contact`.`id` = `post-user`.`contact-id`
STRAIGHT_JOIN `contact` AS `author` ON `author`.`id` = `post-user`.`author-id`
STRAIGHT_JOIN `contact` AS `owner` ON `owner`.`id` = `post-user`.`owner-id`
LEFT JOIN `contact` AS `causer` ON `causer`.`id` = `post-user`.`causer-id`
LEFT JOIN `item-uri` ON `item-uri`.`id` = `post-origin`.`uri-id`
LEFT JOIN `item-uri` AS `thr-parent-item-uri` ON `thr-parent-item-uri`.`id` = `post-origin`.`thr-parent-id`
LEFT JOIN `item-uri` AS `parent-item-uri` ON `parent-item-uri`.`id` = `post-origin`.`parent-uri-id`
LEFT JOIN `item-uri` AS `conversation-item-uri` ON `conversation-item-uri`.`id` = `post-thread-user`.`conversation-id`
LEFT JOIN `item-uri` AS `external-item-uri` ON `external-item-uri`.`id` = `post-user`.`external-id`
LEFT JOIN `verb` ON `verb`.`id` = `post-origin`.`vid`
LEFT JOIN `event` ON `event`.`id` = `post-user`.`event-id`
LEFT JOIN `diaspora-interaction` ON `diaspora-interaction`.`uri-id` = `post-origin`.`uri-id`
LEFT JOIN `post-content` ON `post-content`.`uri-id` = `post-origin`.`uri-id`
LEFT JOIN `item-uri` AS `quote-item-uri` ON `quote-item-uri`.`id` = `post-content`.`quote-uri-id`
LEFT JOIN `post-delivery-data` ON `post-delivery-data`.`uri-id` = `post-origin`.`uri-id`
LEFT JOIN `post-question` ON `post-question`.`uri-id` = `post-origin`.`uri-id`
LEFT JOIN `permissionset` ON `permissionset`.`id` = `post-user`.`psid`
LEFT JOIN `contact` AS `parent-post-author` ON `parent-post-author`.`id` = `post-thread-user`.`author-id`;
--
-- VIEW post-thread-origin-view
--
DROP VIEW IF EXISTS `post-thread-origin-view`;
CREATE VIEW `post-thread-origin-view` AS SELECT
`post-origin`.`id` AS `id`,
`post-origin`.`id` AS `post-user-id`,
`post-origin`.`uid` AS `uid`,
`post-thread-user`.`post-user-id` AS `parent`,
`item-uri`.`uri` AS `uri`,
`post-origin`.`uri-id` AS `uri-id`,
`parent-item-uri`.`uri` AS `parent-uri`,
`post-origin`.`parent-uri-id` AS `parent-uri-id`,
`thr-parent-item-uri`.`uri` AS `thr-parent`,
`post-origin`.`thr-parent-id` AS `thr-parent-id`,
`conversation-item-uri`.`uri` AS `conversation`,
`post-thread-user`.`conversation-id` AS `conversation-id`,
`quote-item-uri`.`uri` AS `quote-uri`,
`post-content`.`quote-uri-id` AS `quote-uri-id`,
`item-uri`.`guid` AS `guid`,
`post-origin`.`wall` AS `wall`,
`post-origin`.`gravity` AS `gravity`,
`external-item-uri`.`uri` AS `extid`,
`post-user`.`external-id` AS `external-id`,
`post-origin`.`created` AS `created`,
`post-user`.`edited` AS `edited`,
`post-thread-user`.`commented` AS `commented`,
`post-origin`.`received` AS `received`,
`post-thread-user`.`changed` AS `changed`,
`post-user`.`post-type` AS `post-type`,
`post-user`.`post-reason` AS `post-reason`,
`post-origin`.`private` AS `private`,
`post-thread-user`.`pubmail` AS `pubmail`,
`post-thread-user`.`ignored` AS `ignored`,
`post-user`.`visible` AS `visible`,
`post-thread-user`.`starred` AS `starred`,
`post-thread-user`.`unseen` AS `unseen`,
`post-user`.`deleted` AS `deleted`,
true AS `origin`,
`post-thread-user`.`mention` AS `mention`,
`post-user`.`global` AS `global`,
EXISTS(SELECT `type` FROM `post-collection` WHERE `type` = 0 AND `uri-id` = `post-thread-user`.`uri-id`) AS `featured`,
`post-thread-user`.`network` AS `network`,
`post-origin`.`vid` AS `vid`,
`post-thread-user`.`psid` AS `psid`,
IF (`post-origin`.`vid` IS NULL, '', `verb`.`name`) AS `verb`,
`post-content`.`title` AS `title`,
`post-content`.`content-warning` AS `content-warning`,
`post-content`.`raw-body` AS `raw-body`,
`post-content`.`body` AS `body`,
`post-content`.`rendered-hash` AS `rendered-hash`,
`post-content`.`rendered-html` AS `rendered-html`,
`post-content`.`language` AS `language`,
`post-content`.`plink` AS `plink`,
`post-content`.`location` AS `location`,
`post-content`.`coord` AS `coord`,
`post-content`.`sensitive` AS `sensitive`,
`post-user`.`restrictions` AS `restrictions`,
`post-content`.`app` AS `app`,
`post-content`.`object-type` AS `object-type`,
`post-content`.`object` AS `object`,
`post-content`.`target-type` AS `target-type`,
`post-content`.`target` AS `target`,
`post-content`.`resource-id` AS `resource-id`,
`post-thread-user`.`contact-id` AS `contact-id`,
`contact`.`uri-id` AS `contact-uri-id`,
`contact`.`url` AS `contact-link`,
`contact`.`addr` AS `contact-addr`,
`contact`.`name` AS `contact-name`,
`contact`.`nick` AS `contact-nick`,
`contact`.`thumb` AS `contact-avatar`,
`contact`.`network` AS `contact-network`,
`contact`.`blocked` AS `contact-blocked`,
`contact`.`hidden` AS `contact-hidden`,
`contact`.`readonly` AS `contact-readonly`,
`contact`.`archive` AS `contact-archive`,
`contact`.`pending` AS `contact-pending`,
`contact`.`rel` AS `contact-rel`,
`contact`.`uid` AS `contact-uid`,
`contact`.`gsid` AS `contact-gsid`,
`contact`.`contact-type` AS `contact-contact-type`,
IF (`post-user`.`network` IN ('apub', 'dfrn', 'dspr', 'stat'), true, `contact`.`writable`) AS `writable`,
`contact`.`self` AS `self`,
`contact`.`id` AS `cid`,
`contact`.`alias` AS `alias`,
`contact`.`photo` AS `photo`,
`contact`.`name-date` AS `name-date`,
`contact`.`uri-date` AS `uri-date`,
`contact`.`avatar-date` AS `avatar-date`,
`contact`.`thumb` AS `thumb`,
`post-thread-user`.`author-id` AS `author-id`,
`author`.`uri-id` AS `author-uri-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`,
`author`.`nick` AS `author-nick`,
`author`.`alias` AS `author-alias`,
IF (`contact`.`url` = `author`.`url` AND `contact`.`thumb` != '', `contact`.`thumb`, `author`.`thumb`) AS `author-avatar`,
`author`.`network` AS `author-network`,
`author`.`blocked` AS `author-blocked`,
`author`.`hidden` AS `author-hidden`,
`author`.`updated` AS `author-updated`,
`author`.`contact-type` AS `author-contact-type`,
`author`.`gsid` AS `author-gsid`,
`post-thread-user`.`owner-id` AS `owner-id`,
`owner`.`uri-id` AS `owner-uri-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`,
`owner`.`nick` AS `owner-nick`,
`owner`.`alias` AS `owner-alias`,
IF (`contact`.`url` = `owner`.`url` AND `contact`.`thumb` != '', `contact`.`thumb`, `owner`.`thumb`) AS `owner-avatar`,
`owner`.`network` AS `owner-network`,
`owner`.`blocked` AS `owner-blocked`,
`owner`.`hidden` AS `owner-hidden`,
`owner`.`updated` AS `owner-updated`,
`owner`.`gsid` AS `owner-gsid`,
`owner`.`contact-type` AS `owner-contact-type`,
`post-thread-user`.`causer-id` AS `causer-id`,
`causer`.`uri-id` AS `causer-uri-id`,
`causer`.`url` AS `causer-link`,
`causer`.`addr` AS `causer-addr`,
`causer`.`name` AS `causer-name`,
`causer`.`nick` AS `causer-nick`,
`causer`.`alias` AS `causer-alias`,
`causer`.`thumb` AS `causer-avatar`,
`causer`.`network` AS `causer-network`,
`causer`.`blocked` AS `causer-blocked`,
`causer`.`hidden` AS `causer-hidden`,
`causer`.`gsid` AS `causer-gsid`,
`causer`.`contact-type` AS `causer-contact-type`,
`post-delivery-data`.`postopts` AS `postopts`,
`post-delivery-data`.`inform` AS `inform`,
`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 (`post-thread-user`.`psid` IS NULL, '', `permissionset`.`allow_cid`) AS `allow_cid`,
IF (`post-thread-user`.`psid` IS NULL, '', `permissionset`.`allow_gid`) AS `allow_gid`,
IF (`post-thread-user`.`psid` IS NULL, '', `permissionset`.`deny_cid`) AS `deny_cid`,
IF (`post-thread-user`.`psid` IS NULL, '', `permissionset`.`deny_gid`) AS `deny_gid`,
`post-user`.`event-id` AS `event-id`,
`event`.`created` AS `event-created`,
`event`.`edited` AS `event-edited`,
`event`.`start` AS `event-start`,
`event`.`finish` AS `event-finish`,
`event`.`summary` AS `event-summary`,
`event`.`desc` AS `event-desc`,
`event`.`location` AS `event-location`,
`event`.`type` AS `event-type`,
`event`.`nofinish` AS `event-nofinish`,
`event`.`ignore` AS `event-ignore`,
`post-question`.`id` AS `question-id`,
`post-question`.`multiple` AS `question-multiple`,
`post-question`.`voters` AS `question-voters`,
`post-question`.`end-time` AS `question-end-time`,
EXISTS(SELECT `uri-id` FROM `post-category` WHERE `post-category`.`uri-id` = `post-thread-user`.`uri-id` AND `post-category`.`uid` = `post-thread-user`.`uid`) AS `has-categories`,
EXISTS(SELECT `id` FROM `post-media` WHERE `post-media`.`uri-id` = `post-thread-user`.`uri-id`) AS `has-media`,
`diaspora-interaction`.`interaction` AS `signed_text`,
`parent-item-uri`.`guid` AS `parent-guid`,
`post-thread-user`.`network` AS `parent-network`,
`post-thread-user`.`author-id` AS `parent-author-id`,
`author`.`url` AS `parent-author-link`,
`author`.`name` AS `parent-author-name`,
`author`.`nick` AS `parent-author-nick`,
`author`.`network` AS `parent-author-network`
FROM `post-origin`
INNER JOIN `post-thread-user` ON `post-thread-user`.`uri-id` = `post-origin`.`uri-id` AND `post-thread-user`.`uid` = `post-origin`.`uid`
INNER JOIN `post-user` ON `post-user`.`id` = `post-origin`.`id`
STRAIGHT_JOIN `contact` ON `contact`.`id` = `post-thread-user`.`contact-id`
STRAIGHT_JOIN `contact` AS `author` ON `author`.`id` = `post-thread-user`.`author-id`
STRAIGHT_JOIN `contact` AS `owner` ON `owner`.`id` = `post-thread-user`.`owner-id`
LEFT JOIN `contact` AS `causer` ON `causer`.`id` = `post-thread-user`.`causer-id`
LEFT JOIN `item-uri` ON `item-uri`.`id` = `post-origin`.`uri-id`
LEFT JOIN `item-uri` AS `thr-parent-item-uri` ON `thr-parent-item-uri`.`id` = `post-origin`.`thr-parent-id`
LEFT JOIN `item-uri` AS `parent-item-uri` ON `parent-item-uri`.`id` = `post-origin`.`parent-uri-id`
LEFT JOIN `item-uri` AS `conversation-item-uri` ON `conversation-item-uri`.`id` = `post-thread-user`.`conversation-id`
LEFT JOIN `item-uri` AS `external-item-uri` ON `external-item-uri`.`id` = `post-user`.`external-id`
LEFT JOIN `verb` ON `verb`.`id` = `post-origin`.`vid`
LEFT JOIN `event` ON `event`.`id` = `post-user`.`event-id`
LEFT JOIN `diaspora-interaction` ON `diaspora-interaction`.`uri-id` = `post-origin`.`uri-id`
LEFT JOIN `post-content` ON `post-content`.`uri-id` = `post-origin`.`uri-id`
LEFT JOIN `item-uri` AS `quote-item-uri` ON `quote-item-uri`.`id` = `post-content`.`quote-uri-id`
LEFT JOIN `post-delivery-data` ON `post-delivery-data`.`uri-id` = `post-origin`.`uri-id`
LEFT JOIN `post-question` ON `post-question`.`uri-id` = `post-origin`.`uri-id`
LEFT JOIN `permissionset` ON `permissionset`.`id` = `post-thread-user`.`psid`;
--
-- VIEW post-user-view
--

View file

@ -68,6 +68,7 @@ Database Tables
| [post-history](help/database/db_post-history) | Post history |
| [post-link](help/database/db_post-link) | Post related external links |
| [post-media](help/database/db_post-media) | Attached media |
| [post-origin](help/database/db_post-origin) | Posts from local users |
| [post-question](help/database/db_post-question) | Question |
| [post-question-option](help/database/db_post-question-option) | Question option |
| [post-searchindex](help/database/db_post-searchindex) | Content for all posts |

View file

@ -0,0 +1,48 @@
Table post-origin
===========
Posts from local users
Fields
------
| Field | Description | Type | Null | Key | Default | Extra |
| ------------- | ------------------------------------------------------------ | ------------------ | ---- | --- | ------------------- | ----- |
| id | | int unsigned | NO | PRI | NULL | |
| uri-id | Id of the item-uri table entry that contains the item uri | int unsigned | NO | | NULL | |
| uid | Owner id which owns this copy of the item | mediumint unsigned | NO | | NULL | |
| parent-uri-id | Id of the item-uri table that contains the parent uri | int unsigned | YES | | NULL | |
| thr-parent-id | Id of the item-uri table that contains the thread parent uri | int unsigned | YES | | NULL | |
| created | Creation timestamp. | datetime | NO | | 0001-01-01 00:00:00 | |
| received | datetime | datetime | NO | | 0001-01-01 00:00:00 | |
| gravity | | tinyint unsigned | NO | | 0 | |
| vid | Id of the verb table entry that contains the activity verbs | smallint unsigned | YES | | NULL | |
| private | 0=public, 1=private, 2=unlisted | tinyint unsigned | NO | | 0 | |
| wall | This item was posted to the wall of uid | boolean | NO | | 0 | |
Indexes
------------
| Name | Fields |
| ----------------- | ------------------- |
| PRIMARY | id |
| uid_uri-id | UNIQUE, uid, uri-id |
| uri-id | uri-id |
| parent-uri-id | parent-uri-id |
| thr-parent-id | thr-parent-id |
| vid | vid |
| parent-uri-id_uid | parent-uri-id, uid |
| uid_wall_received | uid, wall, received |
Foreign Keys
------------
| Field | Target Table | Target Field |
|-------|--------------|--------------|
| uri-id | [item-uri](help/database/db_item-uri) | id |
| uid | [user](help/database/db_user) | uid |
| parent-uri-id | [item-uri](help/database/db_item-uri) | id |
| thr-parent-id | [item-uri](help/database/db_item-uri) | id |
| vid | [verb](help/database/db_verb) | id |
Return to [database documentation](help/database)

View file

@ -21,6 +21,7 @@
namespace Friendica\Content\Widget;
use Friendica\Content\Conversation\Entity\Community;
use Friendica\Core\Renderer;
use Friendica\DI;
use Friendica\Model\Tag;
@ -39,9 +40,9 @@ class TrendingTags
* @return string Formatted HTML code
* @throws \Exception
*/
public static function getHTML(string $content = 'global', int $period = 24): string
public static function getHTML(string $content = Community::GLOBAL, int $period = 24): string
{
if ($content == 'local') {
if ($content == Community::LOCAL) {
$tags = Tag::getLocalTrendingHashtags($period, 20);
} else {
$tags = Tag::getGlobalTrendingHashtags($period, 20);

View file

@ -1335,6 +1335,8 @@ class Item
return 0;
}
Post\Origin::insert($posted_item);
// update the commented timestamp on the parent
if (DI::config()->get('system', 'like_no_comment')) {
// Update when it is a comment

View file

@ -379,6 +379,21 @@ class Post
return self::selectView('post-user-view', $selected, $condition, $params);
}
/**
* Select rows from the post-origin-view view
*
* @param array $selected Array of selected fields, empty for all
* @param array $condition Array of fields for condition
* @param array $params Array of several parameters
*
* @return boolean|object
* @throws \Exception
*/
public static function selectOrigin(array $selected = [], array $condition = [], array $params = [])
{
return self::selectView('post-origin-view', $selected, $condition, $params);
}
/**
* Select rows from the post-view view
*
@ -424,6 +439,21 @@ class Post
return self::selectView('post-thread-view', $selected, $condition, $params);
}
/**
* Select rows from the post-thread-origin-view view
*
* @param array $selected Array of selected fields, empty for all
* @param array $condition Array of fields for condition
* @param array $params Array of several parameters
*
* @return boolean|object
* @throws \Exception
*/
public static function selectOriginThread(array $selected = [], array $condition = [], array $params = [])
{
return self::selectView('post-thread-origin-view', $selected, $condition, $params);
}
/**
* Select rows from the given view for a given user
*
@ -513,6 +543,11 @@ class Post
return self::selectViewForUser('post-timeline-view', $uid, $selected, $condition, $params);
}
public static function selectLocalTimelineForUser(int $uid, array $selected = [], array $condition = [], array $params = [])
{
return self::selectViewForUser('post-timeline-origin-view', $uid, $selected, $condition, $params);
}
/**
* Select rows from the post-thread-user-view view for a given user
*

93
src/Model/Post/Origin.php Normal file
View file

@ -0,0 +1,93 @@
<?php
/**
* @copyright Copyright (C) 2010-2024, the Friendica project
*
* @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 Friendica\Database\DBA;
use \BadMethodCallException;
use Friendica\Database\Database;
use Friendica\DI;
class Origin
{
/**
* Insert a new post origin entry
*
* @param array $fields
* @return boolean was the insert successful?
* @throws \Exception
*/
public static function insert(array $data = []): bool
{
if (!$data['origin'] || ($data['uid'] == 0)) {
return false;
}
$fields = DI::dbaDefinition()->truncateFieldsForTable('post-origin', $data);
return DBA::insert('post-origin', $fields, Database::INSERT_IGNORE);
}
/**
* Update a post origin entry
*
* @param integer $uri_id
* @param integer $uid
* @param array $data
* @param bool $insert_if_missing
* @return bool
* @throws \Exception
*/
public static function update(int $uri_id, int $uid, array $data = [], bool $insert_if_missing = false)
{
if (empty($uri_id)) {
throw new BadMethodCallException('Empty URI_id');
}
$fields = DI::dbaDefinition()->truncateFieldsForTable('post-origin', $data);
// Remove the key fields
unset($fields['uri-id']);
unset($fields['uid']);
if (empty($fields)) {
return true;
}
return DBA::update('post-origin', $fields, ['uri-id' => $uri_id, 'uid' => $uid], $insert_if_missing ? true : []);
}
/**
* Delete a row from the post-origin 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-origin', $conditions, $options);
}
}

View file

@ -85,7 +85,11 @@ class PublicTimeline extends BaseApi
$condition = DBA::mergeConditions($condition, ['gravity' => Item::GRAVITY_PARENT]);
}
$items = Post::selectTimelineForUser($uid, ['uri-id'], $condition, $params);
if ($request['local']) {
$items = Post::selectLocalTimelineForUser($uid, ['uri-id'], $condition, $params);
} else {
$items = Post::selectTimelineForUser($uid, ['uri-id'], $condition, $params);
}
$display_quotes = self::appSupportsQuotes();

View file

@ -26,6 +26,7 @@ use Friendica\App\Mode;
use Friendica\BaseModule;
use Friendica\Content\Conversation\Collection\Timelines;
use Friendica\Content\Conversation\Entity\Channel as ChannelEntity;
use Friendica\Content\Conversation\Entity\Community;
use Friendica\Content\Conversation\Entity\UserDefinedChannel as UserDefinedChannelEntity;
use Friendica\Content\Conversation\Repository\UserDefinedChannel;
use Friendica\Core\Cache\Capability\ICanCache;
@ -685,10 +686,10 @@ class Timeline extends BaseModule
{
$items = $this->selectItems();
if ($this->selectedTab == 'local') {
if ($this->selectedTab == Community::LOCAL) {
$maxpostperauthor = (int)$this->config->get('system', 'max_author_posts_community_page');
$key = 'author-id';
} elseif ($this->selectedTab == 'global') {
} elseif ($this->selectedTab == Community::GLOBAL) {
$maxpostperauthor = (int)$this->config->get('system', 'max_server_posts_community_page');
$key = 'author-gsid';
} else {
@ -754,7 +755,7 @@ class Timeline extends BaseModule
{
$this->order = 'received';
if ($this->selectedTab == 'local') {
if ($this->selectedTab == Community::LOCAL) {
$condition = ["`wall` AND `origin` AND `private` = ?", Item::PUBLIC];
} elseif ($this->selectedTab == 'global') {
$condition = ["`uid` = ? AND `private` = ?", 0, Item::PUBLIC];
@ -790,7 +791,11 @@ class Timeline extends BaseModule
}
$items = [];
$result = Post::selectThreadForUser($this->session->getLocalUserId() ?: 0, ['uri-id', 'received', 'author-id', 'author-gsid'], $condition, $params);
if ($this->selectedTab == Community::LOCAL) {
$result = Post::selectOriginThread(['uri-id', 'received', 'author-id', 'author-gsid'], $condition, $params);
} else {
$result = Post::selectThreadForUser($this->session->getLocalUserId() ?: 0, ['uri-id', 'received', 'author-id', 'author-gsid'], $condition, $params);
}
while ($item = $this->database->fetch($result)) {
$item['comments'] = 0;

View file

@ -22,7 +22,6 @@
namespace Friendica\Module;
use Friendica\BaseModule;
use Friendica\Core\System;
use Friendica\Model\User;
use Friendica\Network\HTTPException;
use Friendica\Protocol\Feed as ProtocolFeed;

View file

@ -204,7 +204,7 @@ class Conversations extends BaseProfile
$condition = DBA::mergeConditions($condition, ["((`gravity` = ? AND `wall`) OR
(`gravity` = ? AND `vid` = ? AND `origin`
AND EXISTS(SELECT `uri-id` FROM `post` WHERE `uri-id` = `post-user-view`.`thr-parent-id` AND `gravity` = ? AND `network` IN (?, ?))))",
AND EXISTS(SELECT `uri-id` FROM `post` WHERE `uri-id` = `post-origin-view`.`thr-parent-id` AND `gravity` = ? AND `network` IN (?, ?))))",
Item::GRAVITY_PARENT, Item::GRAVITY_ACTIVITY, Verb::getID(Activity::ANNOUNCE), Item::GRAVITY_PARENT, Protocol::ACTIVITYPUB, Protocol::DFRN]);
$condition = DBA::mergeConditions($condition, ['uid' => $profile['uid'], 'network' => Protocol::FEDERATED,
@ -213,7 +213,7 @@ class Conversations extends BaseProfile
$pager = new Pager($this->l10n, $this->args->getQueryString(), $itemspage_network);
$params = ['limit' => [$pager->getStart(), $pager->getItemsPerPage()], 'order' => ['received' => true]];
$items_stmt = Post::select(['uri-id', 'thr-parent-id', 'gravity', 'author-id', 'received'], $condition, $params);
$items_stmt = Post::selectOrigin(['uri-id', 'thr-parent-id', 'gravity', 'author-id', 'received'], $condition, $params);
// Set a time stamp for this page. We will make use of it when we
// search for new items (update routine)

View file

@ -1003,8 +1003,6 @@ class Feed
{
$stamp = microtime(true);
$cachekey = 'feed:feed:' . $owner['nickname'] . ':' . $filter . ':' . $last_update;
// Display events in the user's timezone
if (strlen($owner['timezone'])) {
DI::app()->setTimeZone($owner['timezone']);
@ -1012,15 +1010,6 @@ class Feed
$previous_created = $last_update;
// Don't cache when the last item was posted less than 15 minutes ago (Cache duration)
if ((time() - strtotime($owner['last-item'])) < 15 * 60) {
$result = DI::cache()->get($cachekey);
if (!$nocache && !is_null($result)) {
Logger::info('Cached feed duration', ['seconds' => number_format(microtime(true) - $stamp, 3), 'nick' => $owner['nickname'], 'filter' => $filter, 'created' => $previous_created]);
return $result['feed'];
}
}
$check_date = empty($last_update) ? '' : DateTimeFormat::utc($last_update);
$authorid = Contact::getIdForURL($owner['url']);
@ -1046,9 +1035,9 @@ class Feed
$params = ['order' => ['received' => true], 'limit' => $max_items];
if ($filter === 'posts') {
$ret = Post::selectThread(Item::DELIVER_FIELDLIST, $condition, $params);
$ret = Post::selectOriginThread(Item::DELIVER_FIELDLIST, $condition, $params);
} else {
$ret = Post::select(Item::DELIVER_FIELDLIST, $condition, $params);
$ret = Post::selectOrigin(Item::DELIVER_FIELDLIST, $condition, $params);
}
$items = Post::toArray($ret);
@ -1069,9 +1058,6 @@ class Feed
$feeddata = trim($doc->saveXML());
$msg = ['feed' => $feeddata, 'last_update' => $last_update];
DI::cache()->set($cachekey, $msg, Duration::QUARTER_HOUR);
Logger::info('Feed duration', ['seconds' => number_format(microtime(true) - $stamp, 3), 'nick' => $owner['nickname'], 'filter' => $filter, 'created' => $previous_created]);
return $feeddata;

View file

@ -73,6 +73,7 @@ class ExpirePosts
while ($row = Post::fetch($rows)) {
Logger::info('Delete expired item', ['uri-id' => $row['uri-id'], 'guid' => $row['guid']]);
Post\User::delete(['parent-uri-id' => $row['uri-id'], 'uid' => $row['uid']]);
Post\Origin::delete(['parent-uri-id' => $row['uri-id'], 'uid' => $row['uid']]);
}
DBA::close($rows);

View file

@ -56,7 +56,7 @@ use Friendica\Database\DBA;
// This file is required several times during the test in DbaDefinition which justifies this condition
if (!defined('DB_UPDATE_VERSION')) {
define('DB_UPDATE_VERSION', 1559);
define('DB_UPDATE_VERSION', 1560);
}
return [
@ -1459,6 +1459,32 @@ return [
"media-uri-id" => ["media-uri-id"],
]
],
"post-origin" => [
"comment" => "Posts from local users",
"fields" => [
"id" => ["type" => "int unsigned", "not null" => "1", "primary" => "1"],
"uri-id" => ["type" => "int unsigned", "not null" => "1", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the item uri"],
"uid" => ["type" => "mediumint unsigned", "not null" => "1", "foreign" => ["user" => "uid"], "comment" => "Owner id which owns this copy of the item"],
"parent-uri-id" => ["type" => "int unsigned", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table that contains the parent uri"],
"thr-parent-id" => ["type" => "int unsigned", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table that contains the thread parent uri"],
"created" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "Creation timestamp."],
"received" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "datetime"],
"gravity" => ["type" => "tinyint unsigned", "not null" => "1", "default" => "0", "comment" => ""],
"vid" => ["type" => "smallint unsigned", "foreign" => ["verb" => "id", "on delete" => "restrict"], "comment" => "Id of the verb table entry that contains the activity verbs"],
"private" => ["type" => "tinyint unsigned", "not null" => "1", "default" => "0", "comment" => "0=public, 1=private, 2=unlisted"],
"wall" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "This item was posted to the wall of uid"],
],
"indexes" => [
"PRIMARY" => ["id"],
"uid_uri-id" => ["UNIQUE", "uid", "uri-id"],
"uri-id" => ["uri-id"],
"parent-uri-id" => ["parent-uri-id"],
"thr-parent-id" => ["thr-parent-id"],
"vid" => ["vid"],
"parent-uri-id_uid" => ["parent-uri-id", "uid"],
"uid_wall_received" => ["uid", "wall", "received"],
],
],
"post-question" => [
"comment" => "Question",
"fields" => [

View file

@ -143,6 +143,50 @@
STRAIGHT_JOIN `contact` AS `owner` ON `owner`.`id` = `post-user`.`owner-id`
LEFT JOIN `contact` AS `causer` ON `causer`.`id` = `post-user`.`causer-id`"
],
"post-timeline-origin-view" => [
"fields" => [
"uid" => ["post-origin", "uid"],
"uri-id" => ["post-origin", "uri-id"],
"gravity" => ["post-origin", "gravity"],
"created" => ["post-origin", "created"],
"edited" => ["post-user", "edited"],
"commented" => ["post-thread-user", "commented"],
"received" => ["post-origin", "received"],
"changed" => ["post-thread-user", "changed"],
"private" => ["post-origin", "private"],
"visible" => ["post-user", "visible"],
"deleted" => ["post-user", "deleted"],
"origin" => "true",
"global" => ["post-user", "global"],
"network" => ["post-user", "network"],
"protocol" => ["post-user", "protocol"],
"vid" => ["post-origin", "vid"],
"contact-id" => ["post-user", "contact-id"],
"contact-blocked" => ["contact", "blocked"],
"contact-readonly" => ["contact", "readonly"],
"contact-pending" => ["contact", "pending"],
"contact-rel" => ["contact", "rel"],
"contact-uid" => ["contact", "uid"],
"self" => ["contact", "self"],
"author-id" => ["post-user", "author-id"],
"author-blocked" => ["author", "blocked"],
"author-hidden" => ["author", "hidden"],
"author-gsid" => ["author", "gsid"],
"owner-id" => ["post-user", "owner-id"],
"owner-blocked" => ["owner", "blocked"],
"owner-gsid" => ["owner", "gsid"],
"causer-id" => ["post-user", "causer-id"],
"causer-blocked" => ["causer", "blocked"],
"causer-gsid" => ["causer", "gsid"],
],
"query" => "FROM `post-origin`
INNER JOIN `post-user` ON `post-user`.`id` = `post-origin`.`id`
LEFT JOIN `post-thread-user` ON `post-thread-user`.`uri-id` = `post-origin`.`parent-uri-id` AND `post-thread-user`.`uid` = `post-origin`.`uid`
STRAIGHT_JOIN `contact` ON `contact`.`id` = `post-user`.`contact-id`
STRAIGHT_JOIN `contact` AS `author` ON `author`.`id` = `post-user`.`author-id`
STRAIGHT_JOIN `contact` AS `owner` ON `owner`.`id` = `post-user`.`owner-id`
LEFT JOIN `contact` AS `causer` ON `causer`.`id` = `post-user`.`causer-id`"
],
"post-searchindex-user-view" => [
"fields" => [
"uid" => ["post-thread-user", "uid"],
@ -173,6 +217,376 @@
AND NOT EXISTS(SELECT `cid` FROM `user-contact` WHERE `uid` = `post-thread-user`.`uid` AND `cid` IN (`authorcontact`.`id`, `ownercontact`.`id`) AND (`blocked` OR `ignored`))
AND NOT EXISTS(SELECT `gsid` FROM `user-gserver` WHERE `uid` = `post-thread-user`.`uid` AND `gsid` IN (`authorcontact`.`gsid`, `ownercontact`.`gsid`) AND `ignored`)"
],
"post-origin-view" => [
"fields" => [
"id" => ["post-origin", "id"],
"post-user-id" => ["post-origin", "id"],
"uid" => ["post-origin", "uid"],
"parent" => ["post-thread-user", "post-user-id"],
"uri" => ["item-uri", "uri"],
"uri-id" => ["post-origin", "uri-id"],
"parent-uri" => ["parent-item-uri", "uri"],
"parent-uri-id" => ["post-origin", "parent-uri-id"],
"thr-parent" => ["thr-parent-item-uri", "uri"],
"thr-parent-id" => ["post-origin", "thr-parent-id"],
"conversation" => ["conversation-item-uri", "uri"],
"conversation-id" => ["post-thread-user", "conversation-id"],
"quote-uri" => ["quote-item-uri", "uri"],
"quote-uri-id" => ["post-content", "quote-uri-id"],
"guid" => ["item-uri", "guid"],
"wall" => ["post-origin", "wall"],
"gravity" => ["post-origin", "gravity"],
"extid" => ["external-item-uri", "uri"],
"external-id" => ["post-user", "external-id"],
"created" => ["post-origin", "created"],
"edited" => ["post-user", "edited"],
"commented" => ["post-thread-user", "commented"],
"received" => ["post-origin", "received"],
"changed" => ["post-thread-user", "changed"],
"post-type" => ["post-user", "post-type"],
"post-reason" => ["post-user", "post-reason"],
"private" => ["post-origin", "private"],
"pubmail" => ["post-thread-user", "pubmail"],
"visible" => ["post-user", "visible"],
"starred" => ["post-thread-user", "starred"],
"unseen" => ["post-user", "unseen"],
"deleted" => ["post-user", "deleted"],
"origin" => "true",
"parent-origin" => ["post-thread-user", "origin"],
"mention" => ["post-thread-user", "mention"],
"global" => ["post-user", "global"],
"featured" => "EXISTS(SELECT `type` FROM `post-collection` WHERE `type` = 0 AND `uri-id` = `post-origin`.`uri-id`)",
"network" => ["post-user", "network"],
"protocol" => ["post-user", "protocol"],
"vid" => ["post-origin", "vid"],
"psid" => ["post-user", "psid"],
"verb" => "IF (`post-origin`.`vid` IS NULL, '', `verb`.`name`)",
"title" => ["post-content", "title"],
"content-warning" => ["post-content", "content-warning"],
"raw-body" => ["post-content", "raw-body"],
"body" => "IFNULL (`post-content`.`body`, '')",
"rendered-hash" => ["post-content", "rendered-hash"],
"rendered-html" => ["post-content", "rendered-html"],
"language" => ["post-content", "language"],
"plink" => ["post-content", "plink"],
"location" => ["post-content", "location"],
"coord" => ["post-content", "coord"],
"sensitive" => ["post-content", "sensitive"],
"restrictions" => ["post-user", "restrictions"],
"app" => ["post-content", "app"],
"object-type" => ["post-content", "object-type"],
"object" => ["post-content", "object"],
"target-type" => ["post-content", "target-type"],
"target" => ["post-content", "target"],
"resource-id" => ["post-content", "resource-id"],
"contact-id" => ["post-user", "contact-id"],
"contact-uri-id" => ["contact", "uri-id"],
"contact-link" => ["contact", "url"],
"contact-addr" => ["contact", "addr"],
"contact-name" => ["contact", "name"],
"contact-nick" => ["contact", "nick"],
"contact-avatar" => ["contact", "thumb"],
"contact-network" => ["contact", "network"],
"contact-blocked" => ["contact", "blocked"],
"contact-hidden" => ["contact", "hidden"],
"contact-readonly" => ["contact", "readonly"],
"contact-archive" => ["contact", "archive"],
"contact-pending