diff options
| author | 2025-09-14 22:36:01 +0200 | |
|---|---|---|
| committer | 2025-09-14 22:36:01 +0200 | |
| commit | 29446a29f58b484817e6c9798c736e5f531c21ee (patch) | |
| tree | 0648fd296f4e12641d2d7e2ff1be56696dbea1f6 /app/Models/EntryDAO.php | |
| parent | b8af8382f0978d19763a75032128fb623e4f9eb0 (diff) | |
Recovery: skip broken entries during CLI export/import (#7949)
* Recovery: skip broken entries during CLI export/import
fix https://github.com/FreshRSS/FreshRSS/discussions/7927
```
25605/25605 (48 broken)
```
Help with *database malformed* or other corruption.
* Compatibility multiple databases
Diffstat (limited to 'app/Models/EntryDAO.php')
| -rw-r--r-- | app/Models/EntryDAO.php | 32 |
1 files changed, 25 insertions, 7 deletions
diff --git a/app/Models/EntryDAO.php b/app/Models/EntryDAO.php index 4aa7c5056..cd7bcd2ff 100644 --- a/app/Models/EntryDAO.php +++ b/app/Models/EntryDAO.php @@ -27,6 +27,21 @@ class FreshRSS_EntryDAO extends Minz_ModelPdo { return str_replace('INSERT INTO ', 'INSERT IGNORE INTO ', $sql); } + protected static function sqlLimitAll(): string { + // https://dev.mysql.com/doc/refman/9.4/en/select.html + return '18446744073709551615'; // Maximum unsigned BIGINT in MySQL, which neither supports ALL nor -1 + } + + public static function sqlLimit(int $limit = -1, int $offset = 0): string { + if ($limit < 0 && $offset <= 0) { + return ''; + } + if ($limit < 1) { + $limit = static::sqlLimitAll(); + } + return "LIMIT {$limit} OFFSET {$offset}"; + } + public static function sqlRandom(): string { return 'RAND()'; } @@ -739,18 +754,21 @@ SQL; } } - /** @return Traversable<array{id:string,guid:string,title:string,author:string,content:string,link:string,date:int,lastSeen:int, - * hash:string,is_read:bool,is_favorite:bool,id_feed:int,tags:string,attributes:?string}> */ - public function selectAll(?int $limit = null): Traversable { + /** + * @param 'ASC'|'DESC' $order + * @return Traversable<array{id:string,guid:string,title:string,author:string,content:string,link:string,date:int,lastSeen:int, + * hash:string,is_read:bool,is_favorite:bool,id_feed:int,tags:string,attributes:?string}> + */ + public function selectAll(string $order = 'ASC', int $limit = -1, int $offset = 0): Traversable { $content = static::isCompressed() ? 'UNCOMPRESS(content_bin) AS content' : 'content'; $hash = static::sqlHexEncode('hash'); + $order = in_array($order, ['ASC', 'DESC'], true) ? $order : 'ASC'; + $sqlLimit = static::sqlLimit($limit, $offset); $sql = <<<SQL SELECT id, guid, title, author, {$content}, link, date, `lastSeen`, {$hash} AS hash, is_read, is_favorite, id_feed, tags, attributes FROM `_entry` +ORDER BY id {$order} {$sqlLimit} SQL; - if (is_int($limit) && $limit >= 0) { - $sql .= ' ORDER BY id DESC LIMIT ' . $limit; - } $stm = $this->pdo->query($sql); if ($stm !== false) { while (is_array($row = $stm->fetch(PDO::FETCH_ASSOC))) { @@ -762,7 +780,7 @@ SQL; $info = $this->pdo->errorInfo(); /** @var array{0:string,1:int,2:string} $info */ if ($this->autoUpdateDb($info)) { - yield from $this->selectAll(); + yield from $this->selectAll($order, $limit, $offset); } else { Minz_Log::error(__METHOD__ . ' error: ' . json_encode($info)); } |
