initial attempt to remove mysql-related stuff from tt-rss
This commit is contained in:
@@ -85,15 +85,13 @@ class Article extends Handler_Protected {
|
||||
content = ?, content_hash = ? WHERE id = ?");
|
||||
$sth->execute([$content, $content_hash, $ref_id]);
|
||||
|
||||
if (Config::get(Config::DB_TYPE) == "pgsql") {
|
||||
$sth = $pdo->prepare("UPDATE ttrss_entries
|
||||
SET tsvector_combined = to_tsvector( :ts_content)
|
||||
WHERE id = :id");
|
||||
$params = [
|
||||
":ts_content" => mb_substr(\Soundasleep\Html2Text::convert($content), 0, 900000),
|
||||
":id" => $ref_id];
|
||||
$sth->execute($params);
|
||||
}
|
||||
$sth = $pdo->prepare("UPDATE ttrss_entries
|
||||
SET tsvector_combined = to_tsvector( :ts_content)
|
||||
WHERE id = :id");
|
||||
$params = [
|
||||
":ts_content" => mb_substr(\Soundasleep\Html2Text::convert($content), 0, 900000),
|
||||
":id" => $ref_id];
|
||||
$sth->execute($params);
|
||||
|
||||
$sth = $pdo->prepare("UPDATE ttrss_user_entries SET published = true,
|
||||
last_published = NOW() WHERE
|
||||
@@ -130,15 +128,15 @@ class Article extends Handler_Protected {
|
||||
|
||||
if ($row = $sth->fetch()) {
|
||||
$ref_id = $row["id"];
|
||||
if (Config::get(Config::DB_TYPE) == "pgsql"){
|
||||
$sth = $pdo->prepare("UPDATE ttrss_entries
|
||||
SET tsvector_combined = to_tsvector( :ts_content)
|
||||
WHERE id = :id");
|
||||
$params = [
|
||||
":ts_content" => mb_substr(\Soundasleep\Html2Text::convert($content), 0, 900000),
|
||||
":id" => $ref_id];
|
||||
$sth->execute($params);
|
||||
}
|
||||
|
||||
$sth = $pdo->prepare("UPDATE ttrss_entries
|
||||
SET tsvector_combined = to_tsvector( :ts_content)
|
||||
WHERE id = :id");
|
||||
$params = [
|
||||
":ts_content" => mb_substr(\Soundasleep\Html2Text::convert($content), 0, 900000),
|
||||
":id" => $ref_id];
|
||||
$sth->execute($params);
|
||||
|
||||
$sth = $pdo->prepare("INSERT INTO ttrss_user_entries
|
||||
(ref_id, uuid, feed_id, orig_feed_id, owner_uid, published, tag_cache, label_cache,
|
||||
last_read, note, unread, last_published)
|
||||
@@ -465,16 +463,9 @@ class Article extends Handler_Protected {
|
||||
|
||||
static function _purge_orphans(): void {
|
||||
|
||||
// purge orphaned posts in main content table
|
||||
|
||||
if (Config::get(Config::DB_TYPE) == "mysql")
|
||||
$limit_qpart = "LIMIT 5000";
|
||||
else
|
||||
$limit_qpart = "";
|
||||
|
||||
$pdo = Db::pdo();
|
||||
$res = $pdo->query("DELETE FROM ttrss_entries WHERE
|
||||
NOT EXISTS (SELECT ref_id FROM ttrss_user_entries WHERE ref_id = id) $limit_qpart");
|
||||
NOT EXISTS (SELECT ref_id FROM ttrss_user_entries WHERE ref_id = id)");
|
||||
|
||||
if (Debug::enabled()) {
|
||||
$rows = $res->rowCount();
|
||||
|
||||
@@ -24,7 +24,7 @@ class Config {
|
||||
*
|
||||
*/
|
||||
|
||||
/** database type: pgsql or mysql */
|
||||
/** database type: pgsql */
|
||||
const DB_TYPE = "DB_TYPE";
|
||||
|
||||
/** database server hostname */
|
||||
@@ -42,10 +42,6 @@ class Config {
|
||||
/** database server port */
|
||||
const DB_PORT = "DB_PORT";
|
||||
|
||||
/** connection charset for MySQL. if you have a legacy database and/or experience
|
||||
* garbage unicode characters with this option, try setting it to a blank string. */
|
||||
const MYSQL_CHARSET = "MYSQL_CHARSET";
|
||||
|
||||
/** this is a fallback falue for the CLI SAPI, it should be set to a fully-qualified tt-rss URL */
|
||||
const SELF_URL_PATH = "SELF_URL_PATH";
|
||||
|
||||
@@ -204,7 +200,6 @@ class Config {
|
||||
Config::DB_NAME => [ "", Config::T_STRING ],
|
||||
Config::DB_PASS => [ "", Config::T_STRING ],
|
||||
Config::DB_PORT => [ "5432", Config::T_STRING ],
|
||||
Config::MYSQL_CHARSET => [ "UTF8", Config::T_STRING ],
|
||||
Config::SELF_URL_PATH => [ "https://example.com/tt-rss", Config::T_STRING ],
|
||||
Config::SINGLE_USER_MODE => [ "", Config::T_BOOL ],
|
||||
Config::SIMPLE_UPDATE_MODE => [ "", Config::T_BOOL ],
|
||||
@@ -481,25 +476,6 @@ class Config {
|
||||
}
|
||||
/* sanity check stuff */
|
||||
|
||||
/** checks for mysql tables not using InnoDB (tt-rss is incompatible with MyISAM)
|
||||
* @return array<int, array<string, string>> A list of entries identifying tt-rss tables with bad config
|
||||
*/
|
||||
private static function check_mysql_tables() {
|
||||
$pdo = Db::pdo();
|
||||
|
||||
$sth = $pdo->prepare("SELECT engine, table_name FROM information_schema.tables WHERE
|
||||
table_schema = ? AND table_name LIKE 'ttrss_%' AND engine != 'InnoDB'");
|
||||
$sth->execute([self::get(Config::DB_NAME)]);
|
||||
|
||||
$bad_tables = [];
|
||||
|
||||
while ($line = $sth->fetch()) {
|
||||
array_push($bad_tables, $line);
|
||||
}
|
||||
|
||||
return $bad_tables;
|
||||
}
|
||||
|
||||
static function sanity_check(): void {
|
||||
|
||||
/*
|
||||
@@ -604,29 +580,6 @@ class Config {
|
||||
}
|
||||
}
|
||||
|
||||
if (self::get(Config::DB_TYPE) == "mysql") {
|
||||
$bad_tables = self::check_mysql_tables();
|
||||
|
||||
if (count($bad_tables) > 0) {
|
||||
$bad_tables_fmt = [];
|
||||
|
||||
foreach ($bad_tables as $bt) {
|
||||
array_push($bad_tables_fmt, sprintf("%s (%s)", $bt['table_name'], $bt['engine']));
|
||||
}
|
||||
|
||||
$msg = "<p>The following tables use an unsupported MySQL engine: <b>" .
|
||||
implode(", ", $bad_tables_fmt) . "</b>.</p>";
|
||||
|
||||
$msg .= "<p>The only supported engine on MySQL is InnoDB. MyISAM lacks functionality to run
|
||||
tt-rss.
|
||||
Please backup your data (via OPML) and re-import the schema before continuing.</p>
|
||||
<p><b>WARNING: importing the schema would mean LOSS OF ALL YOUR DATA.</b></p>";
|
||||
|
||||
|
||||
array_push($errors, $msg);
|
||||
}
|
||||
}
|
||||
|
||||
if (count($errors) > 0 && php_sapi_name() != "cli") {
|
||||
http_response_code(503); ?>
|
||||
|
||||
|
||||
@@ -9,9 +9,6 @@ class Db {
|
||||
ORM::configure('username', Config::get(Config::DB_USER));
|
||||
ORM::configure('password', Config::get(Config::DB_PASS));
|
||||
ORM::configure('return_result_sets', true);
|
||||
if (Config::get(Config::DB_TYPE) == "mysql" && Config::get(Config::MYSQL_CHARSET)) {
|
||||
ORM::configure('driver_options', array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES ' . Config::get(Config::MYSQL_CHARSET)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -29,13 +26,8 @@ class Db {
|
||||
public static function get_dsn(): string {
|
||||
$db_port = Config::get(Config::DB_PORT) ? ';port=' . Config::get(Config::DB_PORT) : '';
|
||||
$db_host = Config::get(Config::DB_HOST) ? ';host=' . Config::get(Config::DB_HOST) : '';
|
||||
if (Config::get(Config::DB_TYPE) == "mysql" && Config::get(Config::MYSQL_CHARSET)) {
|
||||
$db_charset = ';charset=' . Config::get(Config::MYSQL_CHARSET);
|
||||
} else {
|
||||
$db_charset = '';
|
||||
}
|
||||
|
||||
return Config::get(Config::DB_TYPE) . ':dbname=' . Config::get(Config::DB_NAME) . $db_host . $db_port . $db_charset;
|
||||
return Config::get(Config::DB_TYPE) . ':dbname=' . Config::get(Config::DB_NAME) . $db_host . $db_port;
|
||||
}
|
||||
|
||||
// this really shouldn't be used unless a separate PDO connection is needed
|
||||
@@ -53,20 +45,10 @@ class Db {
|
||||
|
||||
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||
|
||||
if (Config::get(Config::DB_TYPE) == "pgsql") {
|
||||
|
||||
$pdo->query("set client_encoding = 'UTF-8'");
|
||||
$pdo->query("set datestyle = 'ISO, european'");
|
||||
$pdo->query("set TIME ZONE 0");
|
||||
$pdo->query("set cpu_tuple_cost = 0.5");
|
||||
|
||||
} else if (Config::get(Config::DB_TYPE) == "mysql") {
|
||||
$pdo->query("SET time_zone = '+0:0'");
|
||||
|
||||
if (Config::get(Config::MYSQL_CHARSET)) {
|
||||
$pdo->query("SET NAMES " . Config::get(Config::MYSQL_CHARSET));
|
||||
}
|
||||
}
|
||||
$pdo->query("set client_encoding = 'UTF-8'");
|
||||
$pdo->query("set datestyle = 'ISO, european'");
|
||||
$pdo->query("set TIME ZONE 0");
|
||||
$pdo->query("set cpu_tuple_cost = 0.5");
|
||||
|
||||
return $pdo;
|
||||
}
|
||||
@@ -90,15 +72,12 @@ class Db {
|
||||
}
|
||||
|
||||
public static function sql_random_function(): string {
|
||||
if (Config::get(Config::DB_TYPE) == "mysql") {
|
||||
return "RAND()";
|
||||
}
|
||||
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');
|
||||
@@ -106,7 +85,6 @@ class Db {
|
||||
*
|
||||
* @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
|
||||
@@ -114,8 +92,6 @@ class Db {
|
||||
* @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) ";
|
||||
return "$field $operator NOW() - INTERVAL '$quantity $unit' ";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,9 +88,7 @@ class Db_Migrations {
|
||||
$lines = $this->get_lines($version);
|
||||
|
||||
if (count($lines) > 0) {
|
||||
// mysql doesn't support transactions for DDL statements
|
||||
if (Config::get(Config::DB_TYPE) != "mysql")
|
||||
$this->pdo->beginTransaction();
|
||||
$this->pdo->beginTransaction();
|
||||
|
||||
foreach ($lines as $line) {
|
||||
Debug::log($line, Debug::LOG_EXTENDED);
|
||||
@@ -107,8 +105,7 @@ class Db_Migrations {
|
||||
else
|
||||
$this->set_version($version);
|
||||
|
||||
if (Config::get(Config::DB_TYPE) != "mysql")
|
||||
$this->pdo->commit();
|
||||
$this->pdo->commit();
|
||||
|
||||
Debug::log("Migration finished, current version: " . $this->get_version(), Debug::LOG_VERBOSE);
|
||||
|
||||
|
||||
@@ -91,6 +91,7 @@ abstract class FeedItem_Common extends FeedItem {
|
||||
|
||||
$enclosures = $this->xpath->query("media:content", $this->elem);
|
||||
|
||||
/** @var DOMElement $enclosure */
|
||||
foreach ($enclosures as $enclosure) {
|
||||
$enc = new FeedEnclosure();
|
||||
$enc->type = clean($enclosure->getAttribute('type'));
|
||||
@@ -143,6 +144,7 @@ abstract class FeedItem_Common extends FeedItem {
|
||||
|
||||
$enclosures = $this->xpath->query("media:thumbnail", $this->elem);
|
||||
|
||||
/** @var DOMElement $enclosure */
|
||||
foreach ($enclosures as $enclosure) {
|
||||
$enc = new FeedEnclosure();
|
||||
$enc->type = 'image/generic';
|
||||
@@ -193,10 +195,6 @@ abstract class FeedItem_Common extends FeedItem {
|
||||
|
||||
$cat = preg_replace('/[,\'\"]/', "", $cat);
|
||||
|
||||
if (Config::get(Config::DB_TYPE) == "mysql") {
|
||||
$cat = preg_replace('/[\x{10000}-\x{10FFFF}]/u', "\xEF\xBF\xBD", $cat);
|
||||
}
|
||||
|
||||
if (mb_strlen($cat) > 250)
|
||||
$cat = mb_substr($cat, 0, 250);
|
||||
|
||||
|
||||
@@ -217,17 +217,6 @@ class Feeds extends Handler_Protected {
|
||||
|
||||
$id = $line["id"];
|
||||
|
||||
// frontend doesn't expect pdo returning booleans as strings on mysql
|
||||
if (Config::get(Config::DB_TYPE) == "mysql") {
|
||||
foreach (["unread", "marked", "published"] as $k) {
|
||||
if (is_integer($line[$k])) {
|
||||
$line[$k] = $line[$k] === 1;
|
||||
} else {
|
||||
$line[$k] = $line[$k] === "1";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// normalize archived feed
|
||||
if ($line['feed_id'] === null) {
|
||||
$line['feed_id'] = Feeds::FEED_ARCHIVED;
|
||||
@@ -582,7 +571,7 @@ class Feeds extends Handler_Protected {
|
||||
|
||||
function search(): void {
|
||||
print json_encode([
|
||||
"show_language" => Config::get(Config::DB_TYPE) == "pgsql",
|
||||
"show_language" => true,
|
||||
"show_syntax_help" => count(PluginHost::getInstance()->get_hooks(PluginHost::HOOK_SEARCH)) == 0,
|
||||
"all_languages" => Pref_Feeds::get_ts_languages(),
|
||||
"default_language" => Prefs::get(Prefs::DEFAULT_SEARCH_LANGUAGE, $_SESSION['uid'], $_SESSION['profile'] ?? null)
|
||||
@@ -1407,18 +1396,16 @@ class Feeds extends Handler_Protected {
|
||||
list($search_query_part, $search_words) = self::_search_to_sql($search, $search_language, $owner_uid, $profile);
|
||||
}
|
||||
|
||||
if (Config::get(Config::DB_TYPE) == "pgsql") {
|
||||
$test_sth = $pdo->prepare("select $search_query_part
|
||||
FROM ttrss_entries, ttrss_user_entries WHERE id = ref_id limit 1");
|
||||
$test_sth = $pdo->prepare("select $search_query_part
|
||||
FROM ttrss_entries, ttrss_user_entries WHERE id = ref_id limit 1");
|
||||
|
||||
try {
|
||||
$test_sth->execute();
|
||||
} catch (PDOException $e) {
|
||||
// looks like tsquery syntax is invalid
|
||||
$search_query_part = "false";
|
||||
try {
|
||||
$test_sth->execute();
|
||||
} catch (PDOException $e) {
|
||||
// looks like tsquery syntax is invalid
|
||||
$search_query_part = "false";
|
||||
|
||||
$query_error_override = T_sprintf("Incorrect search syntax: %s.", implode(" ", $search_words));
|
||||
}
|
||||
$query_error_override = T_sprintf("Incorrect search syntax: %s.", implode(" ", $search_words));
|
||||
}
|
||||
|
||||
$search_query_part .= " AND ";
|
||||
@@ -1635,11 +1622,7 @@ class Feeds extends Handler_Protected {
|
||||
|
||||
$first_id = 0;
|
||||
|
||||
if (Config::get(Config::DB_TYPE) == "pgsql") {
|
||||
$yyiw_qpart = "to_char(date_entered, 'IYYY-IW') AS yyiw";
|
||||
} else {
|
||||
$yyiw_qpart = "date_format(date_entered, '%Y-%u') AS yyiw";
|
||||
}
|
||||
$yyiw_qpart = "to_char(date_entered, 'IYYY-IW') AS yyiw";
|
||||
|
||||
if (is_numeric($feed)) {
|
||||
// proper override_order applied above
|
||||
@@ -1679,12 +1662,8 @@ class Feeds extends Handler_Protected {
|
||||
|
||||
$sanity_interval_qpart = Db::past_comparison_qpart('date_entered', '>=', 1, 'hour') . ' AND ';
|
||||
|
||||
if (Config::get(Config::DB_TYPE) == "pgsql") {
|
||||
$distinct_columns = str_replace("desc", "", strtolower($order_by));
|
||||
$distinct_qpart = "DISTINCT ON (id, $distinct_columns)";
|
||||
} else {
|
||||
$distinct_qpart = "DISTINCT"; //fallback
|
||||
}
|
||||
$distinct_columns = str_replace("desc", "", strtolower($order_by));
|
||||
$distinct_qpart = "DISTINCT ON (id, $distinct_columns)";
|
||||
|
||||
// except for Labels category
|
||||
if (Prefs::get(Prefs::HEADLINES_NO_DISTINCT, $owner_uid, $profile)
|
||||
@@ -1785,12 +1764,8 @@ class Feeds extends Handler_Protected {
|
||||
if (Prefs::get(Prefs::HEADLINES_NO_DISTINCT, $owner_uid, $profile)) {
|
||||
$distinct_qpart = "";
|
||||
} else {
|
||||
if (Config::get(Config::DB_TYPE) == "pgsql") {
|
||||
$distinct_columns = str_replace("desc", "", strtolower($order_by));
|
||||
$distinct_qpart = "DISTINCT ON (id, $distinct_columns)";
|
||||
} else {
|
||||
$distinct_qpart = "DISTINCT"; //fallback
|
||||
}
|
||||
$distinct_columns = str_replace("desc", "", strtolower($order_by));
|
||||
$distinct_qpart = "DISTINCT ON (id, $distinct_columns)";
|
||||
}
|
||||
|
||||
$query = "SELECT $distinct_qpart
|
||||
@@ -2099,27 +2074,14 @@ class Feeds extends Handler_Protected {
|
||||
else
|
||||
$query_limit = "";
|
||||
|
||||
if (Config::get(Config::DB_TYPE) == "pgsql") {
|
||||
$sth = $pdo->prepare("DELETE FROM ttrss_user_entries
|
||||
USING ttrss_entries
|
||||
WHERE ttrss_entries.id = ref_id AND
|
||||
marked = false AND
|
||||
feed_id = ? AND
|
||||
$query_limit
|
||||
ttrss_entries.date_updated < NOW() - INTERVAL '$purge_interval days'");
|
||||
$sth->execute([$feed_id]);
|
||||
|
||||
} else {
|
||||
$sth = $pdo->prepare("DELETE FROM ttrss_user_entries
|
||||
USING ttrss_user_entries, ttrss_entries
|
||||
WHERE ttrss_entries.id = ref_id AND
|
||||
marked = false AND
|
||||
feed_id = ? AND
|
||||
$query_limit
|
||||
ttrss_entries.date_updated < DATE_SUB(NOW(), INTERVAL $purge_interval DAY)");
|
||||
$sth->execute([$feed_id]);
|
||||
|
||||
}
|
||||
$sth = $pdo->prepare("DELETE FROM ttrss_user_entries
|
||||
USING ttrss_entries
|
||||
WHERE ttrss_entries.id = ref_id AND
|
||||
marked = false AND
|
||||
feed_id = ? AND
|
||||
$query_limit
|
||||
ttrss_entries.date_updated < NOW() - INTERVAL '$purge_interval days'");
|
||||
$sth->execute([$feed_id]);
|
||||
|
||||
$rows_deleted = $sth->rowCount();
|
||||
|
||||
@@ -2286,16 +2248,12 @@ class Feeds extends Handler_Protected {
|
||||
|
||||
$k = mb_strtolower($k);
|
||||
|
||||
if (Config::get(Config::DB_TYPE) == "pgsql") {
|
||||
// A hacky way for phrases (e.g. "hello world") to get through PDO quoting.
|
||||
// Term '"foo bar baz"' becomes '(foo <-> bar <-> baz)' ("<->" meaning "immediately followed by").
|
||||
if (preg_match('/\s+/', $k))
|
||||
$k = '(' . preg_replace('/\s+/', ' <-> ', $k) . ')';
|
||||
// A hacky way for phrases (e.g. "hello world") to get through PDO quoting.
|
||||
// Term '"foo bar baz"' becomes '(foo <-> bar <-> baz)' ("<->" meaning "immediately followed by").
|
||||
if (preg_match('/\s+/', $k))
|
||||
$k = '(' . preg_replace('/\s+/', ' <-> ', $k) . ')';
|
||||
|
||||
array_push($search_query_leftover, $not ? "!$k" : $k);
|
||||
} else {
|
||||
array_push($search_query_leftover, $not ? "-$k" : $k);
|
||||
}
|
||||
array_push($search_query_leftover, $not ? "!$k" : $k);
|
||||
|
||||
if (!$not) array_push($search_words, $k);
|
||||
}
|
||||
@@ -2304,26 +2262,18 @@ class Feeds extends Handler_Protected {
|
||||
|
||||
if (count($search_query_leftover) > 0) {
|
||||
|
||||
if (Config::get(Config::DB_TYPE) == "pgsql") {
|
||||
|
||||
// if there's no joiners consider this a "simple" search and
|
||||
// concatenate everything with &, otherwise don't try to mess with tsquery syntax
|
||||
if (preg_match("/[&|]/", implode(" " , $search_query_leftover))) {
|
||||
$tsquery = $pdo->quote(implode(" ", $search_query_leftover));
|
||||
} else {
|
||||
$tsquery = $pdo->quote(implode(" & ", $search_query_leftover));
|
||||
}
|
||||
|
||||
$search_language = $pdo->quote(mb_strtolower($search_language ?: Prefs::get(Prefs::DEFAULT_SEARCH_LANGUAGE, $owner_uid, $profile)));
|
||||
|
||||
array_push($query_keywords,
|
||||
"(tsvector_combined @@ to_tsquery($search_language, $tsquery))");
|
||||
// if there's no joiners consider this a "simple" search and
|
||||
// concatenate everything with &, otherwise don't try to mess with tsquery syntax
|
||||
if (preg_match("/[&|]/", implode(" " , $search_query_leftover))) {
|
||||
$tsquery = $pdo->quote(implode(" ", $search_query_leftover));
|
||||
} else {
|
||||
$ft_query = $pdo->quote(implode(" ", $search_query_leftover));
|
||||
|
||||
array_push($query_keywords,
|
||||
"MATCH (ttrss_entries.title, ttrss_entries.content) AGAINST ($ft_query IN BOOLEAN MODE)");
|
||||
$tsquery = $pdo->quote(implode(" & ", $search_query_leftover));
|
||||
}
|
||||
|
||||
$search_language = $pdo->quote(mb_strtolower($search_language ?: Prefs::get(Prefs::DEFAULT_SEARCH_LANGUAGE, $owner_uid, $profile)));
|
||||
|
||||
array_push($query_keywords,
|
||||
"(tsvector_combined @@ to_tsquery($search_language, $tsquery))");
|
||||
}
|
||||
|
||||
if (count($query_keywords) > 0)
|
||||
|
||||
@@ -15,12 +15,8 @@ class Pref_Feeds extends Handler_Protected {
|
||||
* @return array<int, string>
|
||||
*/
|
||||
public static function get_ts_languages(): array {
|
||||
if (Config::get(Config::DB_TYPE) == 'pgsql') {
|
||||
return array_map('ucfirst',
|
||||
array_column(ORM::for_table('pg_ts_config')->select('cfgname')->find_array(), 'cfgname'));
|
||||
}
|
||||
|
||||
return [];
|
||||
return array_map('ucfirst',
|
||||
array_column(ORM::for_table('pg_ts_config')->select('cfgname')->find_array(), 'cfgname'));
|
||||
}
|
||||
|
||||
function renameCat(): void {
|
||||
@@ -597,7 +593,7 @@ class Pref_Feeds extends Handler_Protected {
|
||||
"access_level" => $user->access_level
|
||||
],
|
||||
"lang" => [
|
||||
"enabled" => Config::get(Config::DB_TYPE) == "pgsql",
|
||||
"enabled" => true,
|
||||
"default" => Prefs::get(Prefs::DEFAULT_SEARCH_LANGUAGE, $_SESSION['uid'], $profile),
|
||||
"all" => $this::get_ts_languages(),
|
||||
]
|
||||
@@ -653,13 +649,11 @@ class Pref_Feeds extends Handler_Protected {
|
||||
</fieldset>
|
||||
<?php } ?>
|
||||
|
||||
<?php if (Config::get(Config::DB_TYPE) == "pgsql") { ?>
|
||||
<fieldset>
|
||||
<label><?= __('Language:') ?></label>
|
||||
<?= \Controls\select_tag("feed_language", "", $this::get_ts_languages(), ["disabled"=> 1]) ?>
|
||||
<?= $this->_batch_toggle_checkbox("feed_language") ?>
|
||||
</fieldset>
|
||||
<?php } ?>
|
||||
</section>
|
||||
|
||||
<hr/>
|
||||
@@ -1141,12 +1135,6 @@ class Pref_Feeds extends Handler_Protected {
|
||||
|
||||
function inactiveFeeds(): void {
|
||||
|
||||
if (Config::get(Config::DB_TYPE) == "pgsql") {
|
||||
$interval_qpart = "NOW() - INTERVAL '3 months'";
|
||||
} else {
|
||||
$interval_qpart = "DATE_SUB(NOW(), INTERVAL 3 MONTH)";
|
||||
}
|
||||
|
||||
$inactive_feeds = ORM::for_table('ttrss_feeds')
|
||||
->table_alias('f')
|
||||
->select_many('f.id', 'f.title', 'f.site_url', 'f.feed_url')
|
||||
@@ -1158,7 +1146,7 @@ class Pref_Feeds extends Handler_Protected {
|
||||
"(SELECT MAX(ttrss_entries.updated)
|
||||
FROM ttrss_entries
|
||||
JOIN ttrss_user_entries ON ttrss_entries.id = ttrss_user_entries.ref_id
|
||||
WHERE ttrss_user_entries.feed_id = f.id) < $interval_qpart")
|
||||
WHERE ttrss_user_entries.feed_id = f.id) < NOW() - INTERVAL '3 months'")
|
||||
->group_by('f.title')
|
||||
->group_by('f.id')
|
||||
->group_by('f.site_url')
|
||||
|
||||
@@ -591,10 +591,6 @@ class Pref_Prefs extends Handler_Protected {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($pref_name == Prefs::DEFAULT_SEARCH_LANGUAGE && Config::get(Config::DB_TYPE) != "pgsql") {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isset($prefs_available[$pref_name])) {
|
||||
|
||||
$item = $prefs_available[$pref_name];
|
||||
|
||||
@@ -252,33 +252,18 @@ class RPC extends Handler_Protected {
|
||||
$default_interval = (int) Prefs::get_default(Prefs::DEFAULT_UPDATE_INTERVAL);
|
||||
|
||||
// Test if the feed need a update (update interval exceded).
|
||||
if (Config::get(Config::DB_TYPE) == "pgsql") {
|
||||
$update_limit_qpart = "AND ((
|
||||
update_interval = 0
|
||||
AND (p.value IS NULL OR p.value != '-1')
|
||||
AND last_updated < NOW() - CAST((COALESCE(p.value, '$default_interval') || ' minutes') AS INTERVAL)
|
||||
) OR (
|
||||
update_interval > 0
|
||||
AND last_updated < NOW() - CAST((update_interval || ' minutes') AS INTERVAL)
|
||||
) OR (
|
||||
update_interval >= 0
|
||||
AND (p.value IS NULL OR p.value != '-1')
|
||||
AND (last_updated = '1970-01-01 00:00:00' OR last_updated IS NULL)
|
||||
))";
|
||||
} else {
|
||||
$update_limit_qpart = "AND ((
|
||||
update_interval = 0
|
||||
AND (p.value IS NULL OR p.value != '-1')
|
||||
AND last_updated < DATE_SUB(NOW(), INTERVAL CONVERT(COALESCE(p.value, '$default_interval'), SIGNED INTEGER) MINUTE)
|
||||
) OR (
|
||||
update_interval > 0
|
||||
AND last_updated < DATE_SUB(NOW(), INTERVAL update_interval MINUTE)
|
||||
) OR (
|
||||
update_interval >= 0
|
||||
AND (p.value IS NULL OR p.value != '-1')
|
||||
AND (last_updated = '1970-01-01 00:00:00' OR last_updated IS NULL)
|
||||
))";
|
||||
}
|
||||
$update_limit_qpart = "AND ((
|
||||
update_interval = 0
|
||||
AND (p.value IS NULL OR p.value != '-1')
|
||||
AND last_updated < NOW() - CAST((COALESCE(p.value, '$default_interval') || ' minutes') AS INTERVAL)
|
||||
) OR (
|
||||
update_interval > 0
|
||||
AND last_updated < NOW() - CAST((update_interval || ' minutes') AS INTERVAL)
|
||||
) OR (
|
||||
update_interval >= 0
|
||||
AND (p.value IS NULL OR p.value != '-1')
|
||||
AND (last_updated = '1970-01-01 00:00:00' OR last_updated IS NULL)
|
||||
))";
|
||||
|
||||
// Test if feed is currently being updated by another process.
|
||||
$updstart_thresh_qpart = 'AND (last_update_started IS NULL OR '
|
||||
|
||||
@@ -35,11 +35,6 @@ class RSSUtils {
|
||||
return sha1(implode(",", $pluginhost->get_plugin_names()) . $tmp);
|
||||
}
|
||||
|
||||
// Strips utf8mb4 characters (i.e. emoji) for mysql
|
||||
static function strip_utf8mb4(string $str): string {
|
||||
return preg_replace('/[\x{10000}-\x{10FFFF}]/u', "\xEF\xBF\xBD", $str);
|
||||
}
|
||||
|
||||
static function cleanup_feed_browser(): void {
|
||||
$pdo = Db::pdo();
|
||||
$pdo->query("DELETE FROM ttrss_feedbrowser_cache");
|
||||
@@ -123,33 +118,18 @@ class RSSUtils {
|
||||
|
||||
$default_interval = (int) Prefs::get_default(Prefs::DEFAULT_UPDATE_INTERVAL);
|
||||
|
||||
if (Config::get(Config::DB_TYPE) == "pgsql") {
|
||||
$update_limit_qpart = "AND ((
|
||||
update_interval = 0
|
||||
AND (p.value IS NULL OR p.value != '-1')
|
||||
AND last_updated < NOW() - CAST((COALESCE(p.value, '$default_interval') || ' minutes') AS INTERVAL)
|
||||
) OR (
|
||||
update_interval > 0
|
||||
AND last_updated < NOW() - CAST((update_interval || ' minutes') AS INTERVAL)
|
||||
) OR (
|
||||
update_interval >= 0
|
||||
AND (p.value IS NULL OR p.value != '-1')
|
||||
AND (last_updated = '1970-01-01 00:00:00' OR last_updated IS NULL)
|
||||
))";
|
||||
} else {
|
||||
$update_limit_qpart = "AND ((
|
||||
update_interval = 0
|
||||
AND (p.value IS NULL OR p.value != '-1')
|
||||
AND last_updated < DATE_SUB(NOW(), INTERVAL CONVERT(COALESCE(p.value, '$default_interval'), SIGNED INTEGER) MINUTE)
|
||||
) OR (
|
||||
update_interval > 0
|
||||
AND last_updated < DATE_SUB(NOW(), INTERVAL update_interval MINUTE)
|
||||
) OR (
|
||||
update_interval >= 0
|
||||
AND (p.value IS NULL OR p.value != '-1')
|
||||
AND (last_updated = '1970-01-01 00:00:00' OR last_updated IS NULL)
|
||||
))";
|
||||
}
|
||||
$update_limit_qpart = "AND ((
|
||||
update_interval = 0
|
||||
AND (p.value IS NULL OR p.value != '-1')
|
||||
AND last_updated < NOW() - CAST((COALESCE(p.value, '$default_interval') || ' minutes') AS INTERVAL)
|
||||
) OR (
|
||||
update_interval > 0
|
||||
AND last_updated < NOW() - CAST((update_interval || ' minutes') AS INTERVAL)
|
||||
) OR (
|
||||
update_interval >= 0
|
||||
AND (p.value IS NULL OR p.value != '-1')
|
||||
AND (last_updated = '1970-01-01 00:00:00' OR last_updated IS NULL)
|
||||
))";
|
||||
|
||||
// Test if feed is currently being updated by another process.
|
||||
// TODO: Update RPC::updaterandomfeed_real() to also use 10 minutes?
|
||||
@@ -159,10 +139,7 @@ class RSSUtils {
|
||||
$query_limit = $limit ? sprintf("LIMIT %d", $limit) : "";
|
||||
|
||||
// Update the least recently updated feeds first
|
||||
$query_order = "ORDER BY last_updated";
|
||||
|
||||
if (Config::get(Config::DB_TYPE) == "pgsql")
|
||||
$query_order .= " NULLS FIRST";
|
||||
$query_order = "ORDER BY last_updated NULLS FIRST";
|
||||
|
||||
$query = "SELECT f.feed_url, f.last_updated
|
||||
FROM
|
||||
@@ -856,15 +833,6 @@ class RSSUtils {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Yet another episode of "mysql utf8_general_ci is gimped"
|
||||
if (Config::get(Config::DB_TYPE) == "mysql" && Config::get(Config::MYSQL_CHARSET) != "UTF8MB4") {
|
||||
foreach ((array)$e as $prop => $val) {
|
||||
if (is_string($val)) {
|
||||
$e->$prop = self::strip_utf8mb4($val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
array_push($enclosures, $e);
|
||||
}
|
||||
|
||||
@@ -935,16 +903,6 @@ class RSSUtils {
|
||||
|
||||
Debug::log("plugin data: {$entry_plugin_data}", Debug::LOG_VERBOSE);
|
||||
|
||||
// Workaround: 4-byte unicode requires utf8mb4 in MySQL. See https://tt-rss.org/forum/viewtopic.php?f=1&t=3377&p=20077#p20077
|
||||
if (Config::get(Config::DB_TYPE) == "mysql" && Config::get(Config::MYSQL_CHARSET) != "UTF8MB4") {
|
||||
foreach ($article as $k => $v) {
|
||||
// i guess we'll have to take the risk of 4byte unicode labels & tags here
|
||||
if (is_string($article[$k])) {
|
||||
$article[$k] = self::strip_utf8mb4($v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Collect article tags here so we could filter by them: */
|
||||
|
||||
$matched_rules = [];
|
||||
@@ -1186,14 +1144,9 @@ class RSSUtils {
|
||||
|
||||
Debug::log("resulting RID: $entry_ref_id, IID: $entry_int_id", Debug::LOG_VERBOSE);
|
||||
|
||||
if (Config::get(Config::DB_TYPE) == "pgsql")
|
||||
$tsvector_qpart = "tsvector_combined = to_tsvector(:ts_lang, :ts_content),";
|
||||
else
|
||||
$tsvector_qpart = "";
|
||||
|
||||
$sth = $pdo->prepare("UPDATE ttrss_entries
|
||||
SET title = :title,
|
||||
$tsvector_qpart
|
||||
tsvector_combined = to_tsvector(:ts_lang, :ts_content),
|
||||
content = :content,
|
||||
content_hash = :content_hash,
|
||||
updated = :updated,
|
||||
@@ -1212,12 +1165,10 @@ class RSSUtils {
|
||||
":plugin_data" => $entry_plugin_data,
|
||||
":author" => "$entry_author",
|
||||
":lang" => $entry_language,
|
||||
":id" => $ref_id];
|
||||
|
||||
if (Config::get(Config::DB_TYPE) == "pgsql") {
|
||||
$params[":ts_lang"] = $feed_language;
|
||||
$params[":ts_content"] = mb_substr(strip_tags($entry_title) . " " . \Soundasleep\Html2Text::convert($entry_content), 0, 900000);
|
||||
}
|
||||
":id" => $ref_id,
|
||||
":ts_lang" => $feed_language,
|
||||
":ts_content" => mb_substr(strip_tags($entry_title) . " " . \Soundasleep\Html2Text::convert($entry_content), 0, 900000)
|
||||
];
|
||||
|
||||
$sth->execute($params);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user