Select Git revision
PostgresSmartBackend.php
-
Janne Mareike Koschinski authoredJanne Mareike Koschinski authored
PostgresSmartBackend.php 9.62 KiB
<?php
namespace QuasselRestSearch;
require_once 'Backend.php';
class PostgresSmartBackend implements Backend
{
private $db;
private $options;
function __construct(\PDO $db, array $options)
{
$this->db = $db;
$this->db->exec("SET statement_timeout = 5000;");
$this->options = $options;
}
public function findUser(): \PDOStatement
{
return $this->db->prepare("
SELECT *
FROM quasseluser
WHERE quasseluser.username = :username
");
}
private function tsQueryFunction(): string
{
return array_key_exists('tsqueryfunction', $this->options) ? $this->options['tsqueryfunction'] : "plainto_tsquery('english', :query)";
}
public function findInBuffers(): \PDOStatement
{
$tsQueryFunction = $this->tsQueryFunction();
return $this->db->prepare("
SELECT
ranked_messages.bufferid,
ranked_messages.buffername,
ranked_messages.networkname,
ranked_messages.messageid,
ranked_messages.time,
ranked_messages.sender,
ts_headline(replace(replace(ranked_messages.message, '<', '<'), '>', '>'), query, 'HighlightAll=TRUE') AS message
FROM
(SELECT
matching_messages.*,
network.networkname,
sender.sender,
rank()
OVER (
PARTITION BY matching_messages.bufferid
ORDER BY matching_messages.rank_value DESC
) AS rank,
first_value(rank_value)
OVER (
PARTITION BY matching_messages.bufferid
ORDER BY matching_messages.rank_value DESC
) AS max_rank_value
FROM
(SELECT
backlog.messageid,
backlog.bufferid,
buffer.buffername,
buffer.networkid,
backlog.senderid,
backlog.time,
backlog.message,
query,
(
(ts_rank(tsv, query, :config_normalization) ^ :weight_content) *
((CASE
WHEN TYPE IN (1, 4) THEN 1.0
WHEN TYPE IN (2, 1024, 2048, 4096, 16384) THEN 0.75
WHEN TYPE IN (32, 64, 128, 256, 512, 32768, 65536) THEN 0.5
WHEN TYPE IN (8, 16, 8192, 131072) THEN 0.25
ELSE 0.1 END) ^ :weight_type) *
((EXTRACT(EPOCH FROM TIME) / EXTRACT(EPOCH FROM CURRENT_TIMESTAMP)) ^ :weight_time)
) AS rank_value
FROM
backlog
JOIN buffer ON backlog.bufferid = buffer.bufferid
, $tsQueryFunction query
WHERE buffer.userid = :userid
AND (:ignore_since::BOOLEAN OR backlog.time > :since::TIMESTAMP)
AND (:ignore_before::BOOLEAN OR backlog.time < :before::TIMESTAMP)
AND (:ignore_buffer::BOOLEAN OR buffer.buffername ~* :buffer)
AND backlog.type & 23559 > 0
AND backlog.tsv @@ query
) matching_messages
JOIN sender ON matching_messages.senderid = sender.senderid
JOIN network ON matching_messages.networkid = network.networkid
WHERE (:ignore_network::BOOLEAN OR network.networkname ~* :network)
AND (:ignore_sender::BOOLEAN OR sender.sender ~* :sender)
) ranked_messages
WHERE ranked_messages.rank <= :limit
ORDER BY ranked_messages.max_rank_value DESC, ranked_messages.rank_value DESC
");
}
public function findInBuffersCount(): \PDOStatement
{
$tsQueryFunction = $this->tsQueryFunction();
return $this->db->prepare("
SELECT
backlog.bufferid,
COUNT(*) > (:limit::INT + :offset::INT) AS hasmore
FROM
backlog
JOIN buffer ON backlog.bufferid = buffer.bufferid
JOIN sender ON backlog.senderid = sender.senderid
JOIN network ON buffer.networkid = network.networkid
, $tsQueryFunction query
WHERE buffer.userid = :userid
AND (:ignore_since::BOOLEAN OR backlog.time > :since::TIMESTAMP)
AND (:ignore_before::BOOLEAN OR backlog.time < :before::TIMESTAMP)
AND (:ignore_buffer::BOOLEAN OR buffer.buffername ~* :buffer)
AND (:ignore_network::BOOLEAN OR network.networkname ~* :network)
AND (:ignore_sender::BOOLEAN OR sender.sender ~* :sender)
AND backlog.tsv @@ query AND backlog.type & 23559 > 0
GROUP BY backlog.bufferid;
");
}
public function findInBuffer(): \PDOStatement
{
$tsQueryFunction = $this->tsQueryFunction();
return $this->db->prepare("
SELECT
matching_messages.messageid,
matching_messages.time,
sender.sender,
ts_headline(replace(replace(matching_messages.message, '<', '<'), '>', '>'), query, 'HighlightAll=TRUE') AS message
FROM
(SELECT
backlog.messageid,
backlog.bufferid,
buffer.buffername,
buffer.networkid,
backlog.senderid,
backlog.time,
backlog.message,
query,
(
(ts_rank(tsv, query, :config_normalization) ^ :weight_content) *
((CASE
WHEN TYPE IN (1, 4) THEN 1.0
WHEN TYPE IN (2, 1024, 2048, 4096, 16384) THEN 0.75
WHEN TYPE IN (32, 64, 128, 256, 512, 32768, 65536) THEN 0.5
WHEN TYPE IN (8, 16, 8192, 131072) THEN 0.25
ELSE 0.1 END) ^ :weight_type) *
((EXTRACT(EPOCH FROM TIME) / EXTRACT(EPOCH FROM CURRENT_TIMESTAMP)) ^ :weight_time)
) AS rank_value
FROM
backlog
JOIN buffer ON backlog.bufferid = buffer.bufferid
, $tsQueryFunction query
WHERE buffer.userid = :userid
AND buffer.bufferid = :bufferid
AND (:ignore_since::BOOLEAN OR backlog.time > :since::TIMESTAMP)
AND (:ignore_before::BOOLEAN OR backlog.time < :before::TIMESTAMP)
AND backlog.type & 23559 > 0
AND backlog.tsv @@ query
) matching_messages
JOIN sender ON matching_messages.senderid = sender.senderid
JOIN network ON matching_messages.networkid = network.networkid
WHERE (:ignore_sender::BOOLEAN OR sender.sender ~* :sender)
ORDER BY matching_messages.rank_value DESC
LIMIT :limit
OFFSET :offset
");
}
public function findInBufferCount(): \PDOStatement
{
$tsQueryFunction = $this->tsQueryFunction();
return $this->db->prepare("
SELECT
COUNT(*) > (:limit::INT + :offset::INT) AS hasmore
FROM
backlog
JOIN buffer ON backlog.bufferid = buffer.bufferid
JOIN sender ON backlog.senderid = sender.senderid
, $tsQueryFunction query
WHERE buffer.userid = :userid
AND backlog.bufferid = :bufferid
AND (:ignore_since::BOOLEAN OR backlog.time > :since::TIMESTAMP)
AND (:ignore_before::BOOLEAN OR backlog.time < :before::TIMESTAMP)
AND (:ignore_sender::BOOLEAN OR sender.sender ~* :sender)
AND backlog.tsv @@ query AND backlog.type & 23559 > 0
GROUP BY backlog.bufferid;
");
}
public function loadAfter(): \PDOStatement
{
return $this->db->prepare("
SELECT backlog.messageid,
backlog.bufferid,
buffer.buffername,
sender.sender,
backlog.time,
network.networkname,
replace(replace(replace(backlog.message, '&', '&'), '<', '<'), '>', '>') AS message
FROM
backlog
JOIN sender ON backlog.senderid = sender.senderid
JOIN buffer ON backlog.bufferid = buffer.bufferid
JOIN network ON buffer.networkid = network.networkid
WHERE buffer.userid = :userid
AND backlog.bufferid = :bufferid
AND backlog.messageid >= :anchor
ORDER BY backlog.messageid ASC
LIMIT :limit;
");
}
public function loadBefore(): \PDOStatement
{
return $this->db->prepare("
SELECT backlog.messageid,
backlog.bufferid,
buffer.buffername,
sender.sender,
backlog.time,
network.networkname,
replace(replace(replace(backlog.message, '&', '&'), '<', '<'), '>', '>') AS message
FROM
backlog
JOIN sender ON backlog.senderid = sender.senderid
JOIN buffer ON backlog.bufferid = buffer.bufferid
JOIN network ON buffer.networkid = network.networkid
WHERE buffer.userid = :userid
AND backlog.bufferid = :bufferid
AND backlog.messageid < :anchor
ORDER BY backlog.messageid DESC
LIMIT :limit;
");
}
}