From 648d132abe2ef0c5069568e7bab56554cff8b0ce Mon Sep 17 00:00:00 2001 From: Maxence Lange Date: Thu, 6 Dec 2018 18:18:25 -0100 Subject: [PATCH] cleaning and fixing some SQL Signed-off-by: Maxence Lange --- lib/Db/CoreRequestBuilder.php | 54 +--------- lib/Db/NotesRequestBuilder.php | 186 +++++++++++++++++++++++++-------- 2 files changed, 148 insertions(+), 92 deletions(-) diff --git a/lib/Db/CoreRequestBuilder.php b/lib/Db/CoreRequestBuilder.php index bdaaeddb..5b648946 100644 --- a/lib/Db/CoreRequestBuilder.php +++ b/lib/Db/CoreRequestBuilder.php @@ -346,52 +346,6 @@ class CoreRequestBuilder { } - /** - * @param IQueryBuilder $qb - * @param string $recipient - * @param bool $asAuthor - */ - protected function limitToRecipient( - IQueryBuilder &$qb, string $recipient, bool $asAuthor = false - ) { - $expr = $qb->expr(); - $orX = $expr->orX(); - $dbConn = $this->dbConnection; - - if ($asAuthor === true) { - $func = $qb->func(); - $orX->add( - $expr->eq( - $func->lower('attributed_to'), - $func->lower($qb->createNamedParameter($recipient)) - ) - ); - } - - $orX->add($expr->eq('to', $qb->createNamedParameter($recipient))); - $orX->add( - $expr->like( - 'to_array', - $qb->createNamedParameter('%"' . $dbConn->escapeLikeParameter($recipient) . '"%') - ) - ); - $orX->add( - $expr->like( - 'cc', - $qb->createNamedParameter('%"' . $dbConn->escapeLikeParameter($recipient) . '"%') - ) - ); - $orX->add( - $expr->like( - 'bcc', - $qb->createNamedParameter('%"' . $dbConn->escapeLikeParameter($recipient) . '"%') - ) - ); - - $qb->andWhere($orX); - } - - /** * @param IQueryBuilder $qb * @param int $since @@ -401,14 +355,12 @@ class CoreRequestBuilder { if ($since > 0) { $dTime = new \DateTime(); $dTime->setTimestamp($since); - // This line stuck on sqlite $this->limitToDBFieldDateTime($qb, 'published_time', $dTime); } $qb->setMaxResults($limit); - $pf = $this->defaultSelectAlias; - $qb->orderBy($pf . '.creation', 'desc'); + $qb->orderBy($pf . '.published_time', 'desc'); } @@ -523,6 +475,7 @@ class CoreRequestBuilder { $orX = $expr->orX(); $orX->add($expr->lte($field, $qb->createNamedParameter($date, IQueryBuilder::PARAM_DATE))); + if ($orNull === true) { $orX->add($expr->isNull($field)); } @@ -820,7 +773,6 @@ class CoreRequestBuilder { $actor->setCompleteDetails(true); } } + } - - diff --git a/lib/Db/NotesRequestBuilder.php b/lib/Db/NotesRequestBuilder.php index 1e680a68..16591824 100644 --- a/lib/Db/NotesRequestBuilder.php +++ b/lib/Db/NotesRequestBuilder.php @@ -137,54 +137,158 @@ class NotesRequestBuilder extends CoreRequestBuilder { $func = $qb->func(); $pf = $this->defaultSelectAlias . '.'; - $orX = $expr->orX(); - if ($actorId !== '') { - $orX->add($this->exprLimitToDBField($qb, 'attributed_to', $actorId, false)); - } + $on = $expr->orX(); + $on->add($this->exprLimitToRecipient($qb, $actor->getFollowers(), true)); - // list of possible follow (to, to_array, cc, ...) - $orXFollow = $expr->orX(); - $orXFollow->add($expr->eq($func->lower($pf . 'to'), $func->lower('f.follow_id'))); - $orXFollow->add( - $expr->like( - $func->lower($pf . 'to_array'), $func->concat( - $qb->createNamedParameter('%"'), - $func->concat($func->lower('f.follow_id'), $qb->createNamedParameter('"%')) - ) - ) - ); - $orXFollow->add( - $expr->like( - $func->lower($pf . 'cc'), $func->concat( - $qb->createNamedParameter('%"'), - $func->concat($func->lower('f.follow_id'), $qb->createNamedParameter('"%')) - ) - ) - ); - $orXFollow->add( - $expr->like( - $func->lower($pf . 'bcc'), $func->concat( - $qb->createNamedParameter('%"'), - $func->concat($func->lower('f.follow_id'), $qb->createNamedParameter('"%')) - ) - ) - ); + // list of possible recipient as a follower (to, to_array, cc, ...) + $recipientFields = $expr->orX(); + $recipientFields->add($expr->eq($func->lower($pf . 'to'), $func->lower('f.follow_id'))); + $recipientFields->add($this->exprFieldWithinJsonFormat($qb, 'to_array', 'f.follow_id')); + $recipientFields->add($this->exprFieldWithinJsonFormat($qb, 'cc', 'f.follow_id')); + $recipientFields->add($this->exprFieldWithinJsonFormat($qb, 'bcc', 'f.follow_id')); // all possible follow, but linked by followers (actor_id) and accepted follow - $andXFollow = $expr->andX(); - $andXFollow->add($orXFollow); - $andXFollow->add($this->exprLimitToDBField($qb, 'actor_id', $actorId, false, 'f')); - $andXFollow->add($this->exprLimitToDBFieldInt($qb, 'accepted', 1, 'f')); + $crossFollows = $expr->andX(); + $crossFollows->add($recipientFields); + $crossFollows->add($this->exprLimitToDBField($qb, 'actor_id', $actor->getId(), false, 'f')); + $crossFollows->add($this->exprLimitToDBFieldInt($qb, 'accepted', 1, 'f')); + $on->add($crossFollows); - $orX->add($andXFollow); - - // TODO: SQLite does not support RIGHT JOIN -// $qb->rightJoin( $qb->join( - $this->defaultSelectAlias, CoreRequestBuilder::TABLE_SERVER_FOLLOWS, 'f', - $orX + $this->defaultSelectAlias, CoreRequestBuilder::TABLE_SERVER_FOLLOWS, 'f', $on + ); + } + + + /** + * @param IQueryBuilder $qb + * @param string $field + * @param string $fieldRight + * @param string $alias + * + * @return string + */ + protected function exprFieldWithinJsonFormat( + IQueryBuilder $qb, string $field, string $fieldRight, string $alias = '' + ) { + $func = $qb->func(); + $expr = $qb->expr(); + + if ($alias === '') { + $alias = $this->defaultSelectAlias; + } + + $concat = $func->concat( + $qb->createNamedParameter('%"'), + $func->concat($func->lower($fieldRight), $qb->createNamedParameter('"%')) ); + return $expr->iLike($alias . '.' . $field, $concat); + } + + + /** + * @param IQueryBuilder $qb + * @param string $field + * @param string $value + * + * @return string + */ + protected function exprValueWithinJsonFormat(IQueryBuilder $qb, string $field, string $value + ): string { + $dbConn = $this->dbConnection; + $expr = $qb->expr(); + + return $expr->iLike( + $field, + $qb->createNamedParameter('%"' . $dbConn->escapeLikeParameter($value) . '"%') + ); + } + + + /** + * @param IQueryBuilder $qb + * @param string $field + * @param string $value + * + * @return string + */ + protected function exprValueNotWithinJsonFormat(IQueryBuilder $qb, string $field, string $value + ): string { + $dbConn = $this->dbConnection; + $expr = $qb->expr(); + $func = $qb->func(); + + return $expr->notLike( + $func->lower($field), + $qb->createNamedParameter( + '%"' . $func->lower($dbConn->escapeLikeParameter($value)) . '"%' + ) + ); + } + + + /** + * @param IQueryBuilder $qb + * @param string $recipient + * @param bool $asAuthor + */ + protected function limitToRecipient( + IQueryBuilder &$qb, string $recipient, bool $asAuthor = false + ) { + $qb->andWhere($this->exprLimitToRecipient($qb, $recipient, $asAuthor)); + } + + + /** + * @param IQueryBuilder $qb + * @param string $recipient + * @param bool $asAuthor + * + * @return ICompositeExpression + */ + protected function exprLimitToRecipient( + IQueryBuilder &$qb, string $recipient, bool $asAuthor = false + ): ICompositeExpression { + + $expr = $qb->expr(); + $limit = $expr->orX(); + + if ($asAuthor === true) { + $func = $qb->func(); + $limit->add( + $expr->eq( + $func->lower('attributed_to'), + $func->lower($qb->createNamedParameter($recipient)) + ) + ); + } + + $limit->add($expr->eq('to', $qb->createNamedParameter($recipient))); + $limit->add($this->exprValueWithinJsonFormat($qb, 'to_array', $recipient)); + $limit->add($this->exprValueWithinJsonFormat($qb, 'cc', $recipient)); + $limit->add($this->exprValueWithinJsonFormat($qb, 'bcc', $recipient)); + + return $limit; + } + + + /** + * @param IQueryBuilder $qb + * @param string $recipient + */ + protected function filterToRecipient(IQueryBuilder &$qb, string $recipient) { + + $expr = $qb->expr(); + $filter = $expr->andX(); + + $filter->add($expr->neq('to', $qb->createNamedParameter($recipient))); + $filter->add($this->exprValueNotWithinJsonFormat($qb, 'to_array', $recipient)); + $filter->add($this->exprValueNotWithinJsonFormat($qb, 'cc', $recipient)); + $filter->add($this->exprValueNotWithinJsonFormat($qb, 'bcc', $recipient)); + + $qb->andWhere($filter); +// return $filter; }