1
0
mirror of https://github.com/flarum/core.git synced 2025-08-17 22:01:44 +02:00

Compare commits

..

12 Commits

Author SHA1 Message Date
StyleCI Bot
88b5918e3a Apply fixes from StyleCI
[ci skip] [skip ci]
2022-03-24 13:28:40 +00:00
Daniël Klabbers
d0119e7634 Merge branch 'dk/20220318-tag-index' into dk/20220324-performance-test 2022-03-24 14:28:04 +01:00
Daniël Klabbers
726c8f3a9a missed another prefix for tests 2022-03-24 00:35:41 +01:00
StyleCI Bot
8fe1d1cabc Apply fixes from StyleCI
[ci skip] [skip ci]
2022-03-23 23:28:45 +00:00
Daniël Klabbers
d0b4e74b1f fix prefix failing in tests 2022-03-24 00:28:25 +01:00
StyleCI Bot
65c861ab7b Apply fixes from StyleCI
[ci skip] [skip ci]
2022-03-23 20:30:55 +00:00
Daniël Klabbers
cb9fe6930f possibly fixes the issue with post number calculation 2022-03-23 21:30:46 +01:00
flarum-bot
b64003cba5 Bundled output for commit 46f8cf4628
Includes transpiled JS/TS.

[skip ci]
2022-03-23 17:37:18 +00:00
Sami Mazouz
46f8cf4628 fix: Post--by-start-user class not working (#3356) 2022-03-23 18:21:01 +01:00
Daniël Klabbers
3343fde5f2 add distinct and clean up code further 2022-03-23 12:05:03 +01:00
StyleCI Bot
907b1f10aa Apply fixes from StyleCI
[ci skip] [skip ci]
2022-03-18 15:46:30 +00:00
Daniël Klabbers
ae7d31ec16 fix(tags)!: reduce tag filter query from 3+ second
This PR removes the subqueries inserted for each selected tag. As this
caused the query to take over 3 seconds on communities with hundred
million posts.

```sql
and (`discussions`.`id` in (select `discussion_id` from `discussion_tag` where `tag_id` = 105))
```

The above part takes on average 3.85 seconds, with a join it takes 0.00
seconds.

BREAKING CHANGE: extending the query might have different outcome as we
now use a join and no subquery.
2022-03-18 16:40:30 +01:00
7 changed files with 36 additions and 100 deletions

File diff suppressed because one or more lines are too long

View File

@@ -55,23 +55,23 @@ class TagFilterGambit extends AbstractRegexGambit implements FilterInterface
{
$slugs = explode(',', trim($rawSlugs, '"'));
$query->where(function (Builder $query) use ($slugs, $negate) {
foreach ($slugs as $slug) {
if ($slug === 'untagged') {
$query->whereIn('discussions.id', function (Builder $query) {
$query->select('discussion_id')
->from('discussion_tag');
}, 'or', ! $negate);
} else {
$id = $this->tags->getIdForSlug($slug);
$query->whereIn('discussions.id', function (Builder $query) use ($id) {
$query->select('discussion_id')
->from('discussion_tag')
->where('tag_id', $id);
}, 'or', $negate);
$query
->distinct()
->leftJoin('discussion_tag', 'discussions.id', '=', 'discussion_tag.discussion_id')
->where(function (Builder $query) use ($slugs, $negate) {
foreach ($slugs as $slug) {
if ($slug === 'untagged' && ! $negate) {
$query->orWhereNull('discussion_tag.tag_id');
} elseif ($slug === 'untagged' && $negate) {
$query->orWhereNotNull('discussion_tag.tag_id');
} elseif ($id = $this->tags->getIdForSlug($slug)) {
$query->orWhere(
'discussion_tag.tag_id',
$negate ? '!=' : '=',
$id
);
}
}
}
});
});
}
}

View File

@@ -132,7 +132,7 @@ export default abstract class Post<CustomAttrs extends IPostAttrs = IPostAttrs>
classes.push('Post--by-actor');
}
if (user && user?.id() === discussion.attribute('startUserId')) {
if (user && user === discussion.user()) {
classes.push('Post--by-start-user');
}

View File

@@ -48,6 +48,7 @@ class ShowDiscussionController extends AbstractShowController
* {@inheritdoc}
*/
public $include = [
'user',
'posts',
'posts.discussion',
'posts.user',

View File

@@ -1,73 +0,0 @@
<?php
/*
* This file is part of Flarum.
*
* For detailed copyright and license information, please view the
* LICENSE file that was distributed with this source code.
*/
namespace Flarum\Database;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\MySqlConnection;
trait InsertsViaSubqueryTrait
{
/**
* A list that maps attribute names to callables that produce subqueries
* used to calculate the inserted value.
*
* Each callable should take an instance of the model being saved,
* and return an Eloquent query builder that queries for the subquery
* generated value. The result of the query should be one row of one column.
*
* Subquery attributes should be added in the static `boot` method of models
* using this trait.
*
* @var array<string, callable(AbstractModel): Builder>
*/
protected static $subqueryAttributes = [];
/**
* Overriden so that some fields can be inserted via subquery.
* The goal here is to construct a subquery that returns primitives
* for the provided `attributes`, and uses additional subqueries for
* statically-specified subqueryAttributes.
*/
protected function insertAndSetId(Builder $query, $attributes)
{
$subqueryAttrNames = array_keys(static::$subqueryAttributes);
$literalAttributes = array_diff_key($attributes, array_flip($subqueryAttrNames));
/** @var Builder */
$insertRowSubquery = static::query()->limit(1);
foreach ($literalAttributes as $attrName => $value) {
$parameter = $query->getGrammar()->parameter($value);
$insertRowSubquery->addBinding($value, 'select');
$insertRowSubquery->selectRaw("$parameter as $attrName");
}
foreach (static::$subqueryAttributes as $attrName => $callback) {
$insertRowSubquery->selectSub($callback($this), $attrName);
}
$attrNames = array_merge(array_keys($literalAttributes), $subqueryAttrNames);
$query->insertUsing($attrNames, $insertRowSubquery);
// This should be accurate, as it's the same mechanism used by Laravel's `insertGetId`.
// See https://github.com/laravel/framework/blob/master/src/Illuminate/Database/Query/Processors/Processor.php#L30-L37.
/** @var MySqlConnection */
$con = $query->getQuery()->getConnection();
$idRaw = $con->getPdo()->lastInsertId($keyName = $this->getKeyName());
$id = is_numeric($idRaw) ? (int) $idRaw : $idRaw;
$this->setAttribute($keyName, $id);
// This is necessary to get the computed value of saved attributes.
$this->exists = true;
$this->refresh();
}
}

View File

@@ -74,7 +74,7 @@ class PostReplyHandler
// If this is the first post in the discussion, it's technically not a
// "reply", so we won't check for that permission.
if ($discussion->first_post_id !== null) {
if ($discussion->post_number_index > 0) {
$actor->assertCan('reply', $discussion);
}

View File

@@ -10,14 +10,15 @@
namespace Flarum\Post;
use Flarum\Database\AbstractModel;
use Flarum\Database\InsertsViaSubqueryTrait;
use Flarum\Database\ScopeVisibilityTrait;
use Flarum\Discussion\Discussion;
use Flarum\Foundation\EventGeneratorTrait;
use Flarum\Notification\Notification;
use Flarum\Post\Event\Deleted;
use Flarum\User\User;
use Illuminate\Database\ConnectionInterface;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Query\Expression;
/**
* @property int $id
@@ -42,7 +43,6 @@ class Post extends AbstractModel
{
use EventGeneratorTrait;
use ScopeVisibilityTrait;
use InsertsViaSubqueryTrait;
protected $table = 'posts';
@@ -93,7 +93,19 @@ class Post extends AbstractModel
// discussion.
static::creating(function (self $post) {
$post->type = $post::$type;
$post->number = ++$post->discussion->post_number_index;
/** @var ConnectionInterface $db */
$db = static::getConnectionResolver();
$post->number = new Expression('('.$db
->table('posts', 'pn')
->whereRaw($db->getTablePrefix().'pn.discussion_id = '.intval($post->discussion_id))
->select($db->raw('max('.$db->getTablePrefix().'pn.number) + 1'))
->toSql()
.')');
});
static::created(function (self $post) {
$post->refresh();
$post->discussion->save();
});
@@ -104,10 +116,6 @@ class Post extends AbstractModel
});
static::addGlobalScope(new RegisteredTypesScope);
static::$subqueryAttributes['number'] = function (Post $post) {
return static::query()->where('discussion_id', $post->discussion_id)->selectRaw('max(number)+1');
};
}
/**