mirror of
https://git.tt-rss.org/fox/tt-rss.git
synced 2025-10-11 19:11:04 +02:00
Merge branch 'feature/time-comparison-gen' into 'master'
Add and use 'Db::past_comparison_qpart()'. See merge request tt-rss/tt-rss!105
This commit is contained in:
commit
1fc4eed6cd
@ -96,4 +96,26 @@ class Db {
|
|||||||
return "RANDOM()";
|
return "RANDOM()";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper to build a query part comparing a field against a past datetime (determined by "$now - $some_interval")
|
||||||
|
*
|
||||||
|
* The example below could be read as "last_digest_sent is older than 1 day ago".
|
||||||
|
* ```php
|
||||||
|
* Db::past_comparison_qpart('last_digest_sent', '<', 1, 'day');
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* @todo validate value of $unit and fail if invalid (or massage if practical)?
|
||||||
|
* @link https://www.postgresql.org/docs/current/datatype-datetime.html#DATATYPE-INTERVAL-INPUT
|
||||||
|
* @link https://dev.mysql.com/doc/refman/9.2/en/expressions.html#temporal-intervals
|
||||||
|
* @param string $field the table field being checked
|
||||||
|
* @param '<'|'>'|'<='|'>='|'=' $operator the comparison operator
|
||||||
|
* @param positive-int $quantity the amount of $unit
|
||||||
|
* @param 'year'|'month'|'week'|'day'|'hour'|'minute'|'second' $unit the unit of time for $quantity (see links for more info)
|
||||||
|
* @return string the query part string
|
||||||
|
*/
|
||||||
|
static function past_comparison_qpart(string $field, string $operator, int $quantity, string $unit): string {
|
||||||
|
if (Config::get(Config::DB_TYPE) == 'pgsql')
|
||||||
|
return "$field $operator NOW() - INTERVAL '$quantity $unit' ";
|
||||||
|
return "$field $operator DATE_SUB(NOW(), INTERVAL $quantity $unit) ";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,11 +7,7 @@ class Digest
|
|||||||
|
|
||||||
Debug::log("Sending digests, batch of max $user_limit users, headline limit = $limit");
|
Debug::log("Sending digests, batch of max $user_limit users, headline limit = $limit");
|
||||||
|
|
||||||
if (Config::get(Config::DB_TYPE) == "pgsql") {
|
$interval_qpart = Db::past_comparison_qpart('last_digest_sent', '<', 1, 'day');
|
||||||
$interval_qpart = "last_digest_sent < NOW() - INTERVAL '1 days'";
|
|
||||||
} else /* if (Config::get(Config::DB_TYPE) == "mysql") */ {
|
|
||||||
$interval_qpart = "last_digest_sent < DATE_SUB(NOW(), INTERVAL 1 DAY)";
|
|
||||||
}
|
|
||||||
|
|
||||||
$pdo = Db::pdo();
|
$pdo = Db::pdo();
|
||||||
|
|
||||||
@ -107,11 +103,7 @@ class Digest
|
|||||||
|
|
||||||
$affected_ids = array();
|
$affected_ids = array();
|
||||||
|
|
||||||
if (Config::get(Config::DB_TYPE) == "pgsql") {
|
$interval_qpart = Db::past_comparison_qpart('ttrss_entries.date_updated', '>', $days, 'day');
|
||||||
$interval_qpart = "ttrss_entries.date_updated > NOW() - INTERVAL '$days days'";
|
|
||||||
} else /* if (Config::get(Config::DB_TYPE) == "mysql") */ {
|
|
||||||
$interval_qpart = "ttrss_entries.date_updated > DATE_SUB(NOW(), INTERVAL $days DAY)";
|
|
||||||
}
|
|
||||||
|
|
||||||
$pdo = Db::pdo();
|
$pdo = Db::pdo();
|
||||||
|
|
||||||
|
@ -756,33 +756,10 @@ class Feeds extends Handler_Protected {
|
|||||||
$search_qpart = "true";
|
$search_qpart = "true";
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: all this interval stuff needs some generic generator function
|
$date_qpart = match ($mode) {
|
||||||
|
'1day', '1week', '2week' => Db::past_comparison_qpart('date_entered', '<', (int) substr($mode, 0, 1), substr($mode, 1)),
|
||||||
switch ($mode) {
|
default => 'true',
|
||||||
case "1day":
|
};
|
||||||
if (Config::get(Config::DB_TYPE) == "pgsql") {
|
|
||||||
$date_qpart = "date_entered < NOW() - INTERVAL '1 day' ";
|
|
||||||
} else {
|
|
||||||
$date_qpart = "date_entered < DATE_SUB(NOW(), INTERVAL 1 DAY) ";
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "1week":
|
|
||||||
if (Config::get(Config::DB_TYPE) == "pgsql") {
|
|
||||||
$date_qpart = "date_entered < NOW() - INTERVAL '1 week' ";
|
|
||||||
} else {
|
|
||||||
$date_qpart = "date_entered < DATE_SUB(NOW(), INTERVAL 1 WEEK) ";
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "2week":
|
|
||||||
if (Config::get(Config::DB_TYPE) == "pgsql") {
|
|
||||||
$date_qpart = "date_entered < NOW() - INTERVAL '2 week' ";
|
|
||||||
} else {
|
|
||||||
$date_qpart = "date_entered < DATE_SUB(NOW(), INTERVAL 2 WEEK) ";
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
$date_qpart = "true";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_numeric($feed_id_or_tag_name)) {
|
if (is_numeric($feed_id_or_tag_name)) {
|
||||||
$feed_id = (int) $feed_id_or_tag_name;
|
$feed_id = (int) $feed_id_or_tag_name;
|
||||||
@ -853,12 +830,7 @@ class Feeds extends Handler_Protected {
|
|||||||
|
|
||||||
$intl = (int) Prefs::get(Prefs::FRESH_ARTICLE_MAX_AGE, $owner_uid, $profile);
|
$intl = (int) Prefs::get(Prefs::FRESH_ARTICLE_MAX_AGE, $owner_uid, $profile);
|
||||||
|
|
||||||
if (Config::get(Config::DB_TYPE) == "pgsql") {
|
$match_part = Db::past_comparison_qpart('date_entered', '>', $intl, 'hour');
|
||||||
$match_part = "date_entered > NOW() - INTERVAL '$intl hour' ";
|
|
||||||
} else {
|
|
||||||
$match_part = "date_entered > DATE_SUB(NOW(),
|
|
||||||
INTERVAL $intl HOUR) ";
|
|
||||||
}
|
|
||||||
|
|
||||||
$sth = $pdo->prepare("UPDATE ttrss_user_entries
|
$sth = $pdo->prepare("UPDATE ttrss_user_entries
|
||||||
SET unread = false, last_read = NOW() WHERE ref_id IN
|
SET unread = false, last_read = NOW() WHERE ref_id IN
|
||||||
@ -949,15 +921,8 @@ class Feeds extends Handler_Protected {
|
|||||||
} else if ($n_feed == Feeds::FEED_PUBLISHED) {
|
} else if ($n_feed == Feeds::FEED_PUBLISHED) {
|
||||||
$match_part = "published = true";
|
$match_part = "published = true";
|
||||||
} else if ($n_feed == Feeds::FEED_FRESH) {
|
} else if ($n_feed == Feeds::FEED_FRESH) {
|
||||||
$match_part = "unread = true AND score >= 0";
|
|
||||||
|
|
||||||
$intl = (int) Prefs::get(Prefs::FRESH_ARTICLE_MAX_AGE, $owner_uid, $profile);
|
$intl = (int) Prefs::get(Prefs::FRESH_ARTICLE_MAX_AGE, $owner_uid, $profile);
|
||||||
|
$match_part = 'unread = true AND score >= 0 AND ' . Db::past_comparison_qpart('date_entered', '>', $intl, 'hour');
|
||||||
if (Config::get(Config::DB_TYPE) == "pgsql") {
|
|
||||||
$match_part .= " AND date_entered > NOW() - INTERVAL '$intl hour' ";
|
|
||||||
} else {
|
|
||||||
$match_part .= " AND date_entered > DATE_SUB(NOW(), INTERVAL $intl HOUR) ";
|
|
||||||
}
|
|
||||||
|
|
||||||
$need_entries = true;
|
$need_entries = true;
|
||||||
|
|
||||||
@ -1568,13 +1533,8 @@ class Feeds extends Handler_Protected {
|
|||||||
|
|
||||||
}
|
}
|
||||||
} else if ($feed == Feeds::FEED_RECENTLY_READ) { // recently read
|
} else if ($feed == Feeds::FEED_RECENTLY_READ) { // recently read
|
||||||
$query_strategy_part = "unread = false AND last_read IS NOT NULL";
|
$query_strategy_part = 'unread = false AND last_read IS NOT NULL AND '
|
||||||
|
. Db::past_comparison_qpart('last_read', '>', 1, 'day');
|
||||||
if (Config::get(Config::DB_TYPE) == "pgsql") {
|
|
||||||
$query_strategy_part .= " AND last_read > NOW() - INTERVAL '1 DAY' ";
|
|
||||||
} else {
|
|
||||||
$query_strategy_part .= " AND last_read > DATE_SUB(NOW(), INTERVAL 1 DAY) ";
|
|
||||||
}
|
|
||||||
|
|
||||||
$vfeed_query_part = "ttrss_feeds.title AS feed_title,";
|
$vfeed_query_part = "ttrss_feeds.title AS feed_title,";
|
||||||
$allow_archived = true;
|
$allow_archived = true;
|
||||||
@ -1583,15 +1543,10 @@ class Feeds extends Handler_Protected {
|
|||||||
if (!$override_order) $override_order = "last_read DESC";
|
if (!$override_order) $override_order = "last_read DESC";
|
||||||
|
|
||||||
} else if ($feed == Feeds::FEED_FRESH) { // fresh virtual feed
|
} else if ($feed == Feeds::FEED_FRESH) { // fresh virtual feed
|
||||||
$query_strategy_part = "unread = true AND score >= 0";
|
|
||||||
|
|
||||||
$intl = (int) Prefs::get(Prefs::FRESH_ARTICLE_MAX_AGE, $owner_uid, $profile);
|
$intl = (int) Prefs::get(Prefs::FRESH_ARTICLE_MAX_AGE, $owner_uid, $profile);
|
||||||
|
|
||||||
if (Config::get(Config::DB_TYPE) == "pgsql") {
|
$query_strategy_part = 'unread = true AND score >= 0 AND '
|
||||||
$query_strategy_part .= " AND date_entered > NOW() - INTERVAL '$intl hour' ";
|
. Db::past_comparison_qpart('date_entered', '>', $intl, 'hour');
|
||||||
} else {
|
|
||||||
$query_strategy_part .= " AND date_entered > DATE_SUB(NOW(), INTERVAL $intl HOUR) ";
|
|
||||||
}
|
|
||||||
|
|
||||||
$vfeed_query_part = "ttrss_feeds.title AS feed_title,";
|
$vfeed_query_part = "ttrss_feeds.title AS feed_title,";
|
||||||
} else if ($feed == Feeds::FEED_ALL) { // all articles virtual feed
|
} else if ($feed == Feeds::FEED_ALL) { // all articles virtual feed
|
||||||
@ -1712,13 +1667,12 @@ class Feeds extends Handler_Protected {
|
|||||||
if ($feed == Feeds::FEED_FRESH)
|
if ($feed == Feeds::FEED_FRESH)
|
||||||
$first_id_query_strategy_part = "true";
|
$first_id_query_strategy_part = "true";
|
||||||
|
|
||||||
if (Config::get(Config::DB_TYPE) == "pgsql") {
|
$sanity_interval_qpart = Db::past_comparison_qpart('date_entered', '>=', 1, 'hour') . ' AND ';
|
||||||
$sanity_interval_qpart = "date_entered >= NOW() - INTERVAL '1 hour' AND";
|
|
||||||
|
|
||||||
|
if (Config::get(Config::DB_TYPE) == "pgsql") {
|
||||||
$distinct_columns = str_replace("desc", "", strtolower($order_by));
|
$distinct_columns = str_replace("desc", "", strtolower($order_by));
|
||||||
$distinct_qpart = "DISTINCT ON (id, $distinct_columns)";
|
$distinct_qpart = "DISTINCT ON (id, $distinct_columns)";
|
||||||
} else {
|
} else {
|
||||||
$sanity_interval_qpart = "date_entered >= DATE_SUB(NOW(), INTERVAL 1 hour) AND";
|
|
||||||
$distinct_qpart = "DISTINCT"; //fallback
|
$distinct_qpart = "DISTINCT"; //fallback
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -281,11 +281,8 @@ class RPC extends Handler_Protected {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Test if feed is currently being updated by another process.
|
// Test if feed is currently being updated by another process.
|
||||||
if (Config::get(Config::DB_TYPE) == "pgsql") {
|
$updstart_thresh_qpart = 'AND (last_update_started IS NULL OR '
|
||||||
$updstart_thresh_qpart = "AND (last_update_started IS NULL OR last_update_started < NOW() - INTERVAL '5 minutes')";
|
. Db::past_comparison_qpart('last_update_started', '<', 5, 'minute') . ')';
|
||||||
} else {
|
|
||||||
$updstart_thresh_qpart = "AND (last_update_started IS NULL OR last_update_started < DATE_SUB(NOW(), INTERVAL 5 MINUTE))";
|
|
||||||
}
|
|
||||||
|
|
||||||
$random_qpart = Db::sql_random_function();
|
$random_qpart = Db::sql_random_function();
|
||||||
|
|
||||||
@ -528,11 +525,7 @@ class RPC extends Handler_Protected {
|
|||||||
$data["labels"] = Labels::get_all($_SESSION["uid"]);
|
$data["labels"] = Labels::get_all($_SESSION["uid"]);
|
||||||
|
|
||||||
if (Config::get(Config::LOG_DESTINATION) == 'sql' && $_SESSION['access_level'] >= UserHelper::ACCESS_LEVEL_ADMIN) {
|
if (Config::get(Config::LOG_DESTINATION) == 'sql' && $_SESSION['access_level'] >= UserHelper::ACCESS_LEVEL_ADMIN) {
|
||||||
if (Config::get(Config::DB_TYPE) == 'pgsql') {
|
$log_interval = Db::past_comparison_qpart('created_at', '>', 1, 'hour');
|
||||||
$log_interval = "created_at > NOW() - interval '1 hour'";
|
|
||||||
} else {
|
|
||||||
$log_interval = "created_at > DATE_SUB(NOW(), INTERVAL 1 HOUR)";
|
|
||||||
}
|
|
||||||
|
|
||||||
$sth = $pdo->prepare("SELECT COUNT(id) AS cid
|
$sth = $pdo->prepare("SELECT COUNT(id) AS cid
|
||||||
FROM ttrss_error_log
|
FROM ttrss_error_log
|
||||||
|
@ -103,13 +103,8 @@ class RSSUtils {
|
|||||||
if (!Config::get(Config::SINGLE_USER_MODE) && Config::get(Config::DAEMON_UPDATE_LOGIN_LIMIT) > 0) {
|
if (!Config::get(Config::SINGLE_USER_MODE) && Config::get(Config::DAEMON_UPDATE_LOGIN_LIMIT) > 0) {
|
||||||
$login_limit = (int) Config::get(Config::DAEMON_UPDATE_LOGIN_LIMIT);
|
$login_limit = (int) Config::get(Config::DAEMON_UPDATE_LOGIN_LIMIT);
|
||||||
|
|
||||||
if (Config::get(Config::DB_TYPE) == "pgsql") {
|
$login_thresh_qpart = 'AND ' . Db::past_comparison_qpart('last_login', '>=', $login_limit, 'day');
|
||||||
$login_thresh_qpart = "AND last_login >= NOW() - INTERVAL '$login_limit days'";
|
$not_logged_in_users_query = Db::past_comparison_qpart('last_login', '<', $login_limit, 'day');
|
||||||
$not_logged_in_users_query = "last_login < NOW() - INTERVAL '$login_limit days'";
|
|
||||||
} else {
|
|
||||||
$login_thresh_qpart = "AND last_login >= DATE_SUB(NOW(), INTERVAL $login_limit DAY)";
|
|
||||||
$not_logged_in_users_query = "last_login < DATE_SUB(NOW(), INTERVAL $login_limit DAY)";
|
|
||||||
}
|
|
||||||
|
|
||||||
$not_logged_in_users = ORM::for_table('ttrss_users')
|
$not_logged_in_users = ORM::for_table('ttrss_users')
|
||||||
->where_raw($not_logged_in_users_query)
|
->where_raw($not_logged_in_users_query)
|
||||||
@ -157,11 +152,9 @@ class RSSUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Test if feed is currently being updated by another process.
|
// Test if feed is currently being updated by another process.
|
||||||
if (Config::get(Config::DB_TYPE) == "pgsql") {
|
// TODO: Update RPC::updaterandomfeed_real() to also use 10 minutes?
|
||||||
$updstart_thresh_qpart = "AND (last_update_started IS NULL OR last_update_started < NOW() - INTERVAL '10 minutes')";
|
$updstart_thresh_qpart = 'AND (last_update_started IS NULL OR '
|
||||||
} else {
|
. Db::past_comparison_qpart('last_update_started', '<', 10, 'minute') . ')';
|
||||||
$updstart_thresh_qpart = "AND (last_update_started IS NULL OR last_update_started < DATE_SUB(NOW(), INTERVAL 10 MINUTE))";
|
|
||||||
}
|
|
||||||
|
|
||||||
$query_limit = $limit ? sprintf("LIMIT %d", $limit) : "";
|
$query_limit = $limit ? sprintf("LIMIT %d", $limit) : "";
|
||||||
|
|
||||||
@ -395,11 +388,7 @@ class RSSUtils {
|
|||||||
/** @var DiskCache $cache */
|
/** @var DiskCache $cache */
|
||||||
$cache = DiskCache::instance('feeds');
|
$cache = DiskCache::instance('feeds');
|
||||||
|
|
||||||
if (Config::get(Config::DB_TYPE) == "pgsql") {
|
$favicon_interval_qpart = Db::past_comparison_qpart('favicon_last_checked', '<', 12, 'hour');
|
||||||
$favicon_interval_qpart = "favicon_last_checked < NOW() - INTERVAL '12 hour'";
|
|
||||||
} else {
|
|
||||||
$favicon_interval_qpart = "favicon_last_checked < DATE_SUB(NOW(), INTERVAL 12 HOUR)";
|
|
||||||
}
|
|
||||||
|
|
||||||
$feed_obj = ORM::for_table('ttrss_feeds')
|
$feed_obj = ORM::for_table('ttrss_feeds')
|
||||||
->select_expr("ttrss_feeds.*,
|
->select_expr("ttrss_feeds.*,
|
||||||
@ -1462,16 +1451,9 @@ class RSSUtils {
|
|||||||
|
|
||||||
static function expire_error_log(): void {
|
static function expire_error_log(): void {
|
||||||
Debug::log("Removing old error log entries...");
|
Debug::log("Removing old error log entries...");
|
||||||
|
|
||||||
$pdo = Db::pdo();
|
$pdo = Db::pdo();
|
||||||
|
$pdo->query('DELETE FROM ttrss_error_log
|
||||||
if (Config::get(Config::DB_TYPE) == "pgsql") {
|
WHERE ' . Db::past_comparison_qpart('created_at', '<', 7, 'day'));
|
||||||
$pdo->query("DELETE FROM ttrss_error_log
|
|
||||||
WHERE created_at < NOW() - INTERVAL '7 days'");
|
|
||||||
} else {
|
|
||||||
$pdo->query("DELETE FROM ttrss_error_log
|
|
||||||
WHERE created_at < DATE_SUB(NOW(), INTERVAL 7 DAY)");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1716,13 +1698,8 @@ class RSSUtils {
|
|||||||
|
|
||||||
$pdo->beginTransaction();
|
$pdo->beginTransaction();
|
||||||
|
|
||||||
$days = Config::get(Config::DAEMON_UNSUCCESSFUL_DAYS_LIMIT);
|
$interval_query = Db::past_comparison_qpart('last_successful_update', '<', Config::get(Config::DAEMON_UNSUCCESSFUL_DAYS_LIMIT), 'day')
|
||||||
|
. ' AND ' . Db::past_comparison_qpart('last_updated', '>', 1, 'day');
|
||||||
if (Config::get(Config::DB_TYPE) == "pgsql") {
|
|
||||||
$interval_query = "last_successful_update < NOW() - INTERVAL '$days days' AND last_updated > NOW() - INTERVAL '1 days'";
|
|
||||||
} else /* if (Config::get(Config::DB_TYPE) == "mysql") */ {
|
|
||||||
$interval_query = "last_successful_update < DATE_SUB(NOW(), INTERVAL $days DAY) AND last_updated > DATE_SUB(NOW(), INTERVAL 1 DAY)";
|
|
||||||
}
|
|
||||||
|
|
||||||
$sth = $pdo->prepare("SELECT id, title, owner_uid
|
$sth = $pdo->prepare("SELECT id, title, owner_uid
|
||||||
FROM ttrss_feeds
|
FROM ttrss_feeds
|
||||||
|
@ -33,14 +33,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function cleanup_tags(int $days = 14, int $limit = 1000): int {
|
function cleanup_tags(int $days = 14, int $limit = 1000): int {
|
||||||
|
$interval_query = Db::past_comparison_qpart('e.date_updated', '<', $days, 'day');
|
||||||
$days = (int) $days;
|
|
||||||
|
|
||||||
if (Config::get(Config::DB_TYPE) == "pgsql") {
|
|
||||||
$interval_query = "e.date_updated < NOW() - INTERVAL '$days days'";
|
|
||||||
} else /*if (Config::get(Config::DB_TYPE) == "mysql") */ {
|
|
||||||
$interval_query = "e.date_updated < DATE_SUB(NOW(), INTERVAL $days DAY)";
|
|
||||||
}
|
|
||||||
|
|
||||||
$tags_deleted = 0;
|
$tags_deleted = 0;
|
||||||
$limit_part = 500;
|
$limit_part = 500;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user