浏览代码

Ready for year 2038 (#5570)

* Ready for year 2038
Fix https://github.com/FreshRSS/FreshRSS/discussions/5569
Requires PHP on a 64-bit platform to take advantage of it.
https://en.wikipedia.org/wiki/Year_2038_problem

* Allows dates past 2038
Rework of https://github.com/FreshRSS/FreshRSS/pull/3259
https://github.com/FreshRSS/FreshRSS/issues/3258

* Auto alter columns

* Changelog
Alexandre Alapetite 2 年之前
父节点
当前提交
21a279179a
共有 6 个文件被更改,包括 53 次插入19 次删除
  1. 2 1
      CHANGELOG.md
  2. 14 1
      app/Models/DatabaseDAO.php
  3. 0 2
      app/Models/EntryDAO.php
  4. 16 5
      app/SQL/install.sql.mysql.php
  5. 16 5
      app/SQL/install.sql.pgsql.php
  6. 5 5
      app/SQL/install.sql.sqlite.php

+ 2 - 1
CHANGELOG.md

@@ -5,7 +5,8 @@
 * Compatibility
 * Compatibility
 	* Require PHP 7.4+, and implement *typed properties* [#5720](https://github.com/FreshRSS/FreshRSS/pull/5720)
 	* Require PHP 7.4+, and implement *typed properties* [#5720](https://github.com/FreshRSS/FreshRSS/pull/5720)
 * Features
 * Features
-	* Increase SQL (`VARCHAR`) text fields to maximum possible [#5756](https://github.com/FreshRSS/FreshRSS/pull/5756)
+	* Increase SQL (`VARCHAR`) text fields length to maximum possible [#5756](https://github.com/FreshRSS/FreshRSS/pull/5756)
+	* Increase SQL date fields to 64-bit to be ready for year 2038+ [#5570](https://github.com/FreshRSS/FreshRSS/pull/5570)
 * Misc.
 * Misc.
 	* Code improvements [#5511](https://github.com/FreshRSS/FreshRSS/pull/5511)
 	* Code improvements [#5511](https://github.com/FreshRSS/FreshRSS/pull/5511)
 
 

+ 14 - 1
app/Models/DatabaseDAO.php

@@ -20,7 +20,7 @@ class FreshRSS_DatabaseDAO extends Minz_ModelPdo {
 	public const LENGTH_INDEX_UNICODE = 191;
 	public const LENGTH_INDEX_UNICODE = 191;
 
 
 	public function create(): string {
 	public function create(): string {
-		require(APP_PATH . '/SQL/install.sql.' . $this->pdo->dbType() . '.php');
+		require_once(APP_PATH . '/SQL/install.sql.' . $this->pdo->dbType() . '.php');
 		$db = FreshRSS_Context::$system_conf->db;
 		$db = FreshRSS_Context::$system_conf->db;
 
 
 		try {
 		try {
@@ -214,9 +214,22 @@ SQL;
 		return $ok;
 		return $ok;
 	}
 	}
 
 
+	private function ensureYear2038Compatible(): bool {
+		if ($this->pdo->dbType() !== 'sqlite') {
+			include_once(APP_PATH . '/SQL/install.sql.' . $this->pdo->dbType() . '.php');
+			if ($this->pdo->exec($GLOBALS['SQL_UPDATE_YEAR_2038']) === false) {	//FreshRSS 1.23
+				Minz_Log::error('SQL error ' . __METHOD__ . json_encode($this->pdo->errorInfo()));
+				return false;
+			}
+		}
+		return true;
+	}
+
 	public function minorDbMaintenance(): void {
 	public function minorDbMaintenance(): void {
 		$catDAO = FreshRSS_Factory::createCategoryDao();
 		$catDAO = FreshRSS_Factory::createCategoryDao();
 		$catDAO->resetDefaultCategoryName();
 		$catDAO->resetDefaultCategoryName();
+
+		$this->ensureYear2038Compatible();
 	}
 	}
 
 
 	private static function stdError(string $error): bool {
 	private static function stdError(string $error): bool {

+ 0 - 2
app/Models/EntryDAO.php

@@ -123,7 +123,6 @@ SQL;
 			$valuesTmp['link'] = substr($valuesTmp['link'], 0, 32768);
 			$valuesTmp['link'] = substr($valuesTmp['link'], 0, 32768);
 			$valuesTmp['link'] = safe_ascii($valuesTmp['link']);
 			$valuesTmp['link'] = safe_ascii($valuesTmp['link']);
 			$this->addEntryPrepared->bindParam(':link', $valuesTmp['link']);
 			$this->addEntryPrepared->bindParam(':link', $valuesTmp['link']);
-			$valuesTmp['date'] = min($valuesTmp['date'], 2147483647);
 			$this->addEntryPrepared->bindParam(':date', $valuesTmp['date'], PDO::PARAM_INT);
 			$this->addEntryPrepared->bindParam(':date', $valuesTmp['date'], PDO::PARAM_INT);
 			if (empty($valuesTmp['lastSeen'])) {
 			if (empty($valuesTmp['lastSeen'])) {
 				$valuesTmp['lastSeen'] = time();
 				$valuesTmp['lastSeen'] = time();
@@ -229,7 +228,6 @@ SQL;
 			$valuesTmp['link'] = substr($valuesTmp['link'], 0, 32768);
 			$valuesTmp['link'] = substr($valuesTmp['link'], 0, 32768);
 			$valuesTmp['link'] = safe_ascii($valuesTmp['link']);
 			$valuesTmp['link'] = safe_ascii($valuesTmp['link']);
 			$this->updateEntryPrepared->bindParam(':link', $valuesTmp['link']);
 			$this->updateEntryPrepared->bindParam(':link', $valuesTmp['link']);
-			$valuesTmp['date'] = min($valuesTmp['date'], 2147483647);
 			$this->updateEntryPrepared->bindParam(':date', $valuesTmp['date'], PDO::PARAM_INT);
 			$this->updateEntryPrepared->bindParam(':date', $valuesTmp['date'], PDO::PARAM_INT);
 			$this->updateEntryPrepared->bindParam(':last_seen', $valuesTmp['lastSeen'], PDO::PARAM_INT);
 			$this->updateEntryPrepared->bindParam(':last_seen', $valuesTmp['lastSeen'], PDO::PARAM_INT);
 			if ($valuesTmp['is_read'] === null) {
 			if ($valuesTmp['is_read'] === null) {

+ 16 - 5
app/SQL/install.sql.mysql.php

@@ -24,7 +24,7 @@ CREATE TABLE IF NOT EXISTS `_feed` (
 	`name` VARCHAR(191) NOT NULL,
 	`name` VARCHAR(191) NOT NULL,
 	`website` TEXT CHARACTER SET latin1 COLLATE latin1_bin,
 	`website` TEXT CHARACTER SET latin1 COLLATE latin1_bin,
 	`description` TEXT,
 	`description` TEXT,
-	`lastUpdate` INT(11) DEFAULT 0,	-- Until year 2038
+	`lastUpdate` BIGINT DEFAULT 0,
 	`priority` TINYINT(2) NOT NULL DEFAULT 10,
 	`priority` TINYINT(2) NOT NULL DEFAULT 10,
 	`pathEntries` VARCHAR(65535) DEFAULT NULL,
 	`pathEntries` VARCHAR(65535) DEFAULT NULL,
 	`httpAuth` VARCHAR(1024) DEFAULT NULL,
 	`httpAuth` VARCHAR(1024) DEFAULT NULL,
@@ -47,8 +47,8 @@ CREATE TABLE IF NOT EXISTS `_entry` (
 	`author` VARCHAR(65535),
 	`author` VARCHAR(65535),
 	`content_bin` MEDIUMBLOB,	-- v0.7
 	`content_bin` MEDIUMBLOB,	-- v0.7
 	`link` VARCHAR(32768) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL,
 	`link` VARCHAR(32768) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL,
-	`date` INT(11),	-- Until year 2038
-	`lastSeen` INT(11) DEFAULT 0,	-- v1.1.1, Until year 2038
+	`date` BIGINT,
+	`lastSeen` BIGINT DEFAULT 0,
 	`hash` BINARY(16),	-- v1.1.1
 	`hash` BINARY(16),	-- v1.1.1
 	`is_read` BOOLEAN NOT NULL DEFAULT 0,
 	`is_read` BOOLEAN NOT NULL DEFAULT 0,
 	`is_favorite` BOOLEAN NOT NULL DEFAULT 0,
 	`is_favorite` BOOLEAN NOT NULL DEFAULT 0,
@@ -74,8 +74,8 @@ CREATE TABLE IF NOT EXISTS `_entrytmp` (	-- v1.7
 	`author` VARCHAR(65535),
 	`author` VARCHAR(65535),
 	`content_bin` MEDIUMBLOB,
 	`content_bin` MEDIUMBLOB,
 	`link` VARCHAR(32768) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL,
 	`link` VARCHAR(32768) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL,
-	`date` INT(11),
-	`lastSeen` INT(11) DEFAULT 0,
+	`date` BIGINT,
+	`lastSeen` BIGINT DEFAULT 0,
 	`hash` BINARY(16),
 	`hash` BINARY(16),
 	`is_read` BOOLEAN NOT NULL DEFAULT 0,
 	`is_read` BOOLEAN NOT NULL DEFAULT 0,
 	`is_favorite` BOOLEAN NOT NULL DEFAULT 0,
 	`is_favorite` BOOLEAN NOT NULL DEFAULT 0,
@@ -112,3 +112,14 @@ SQL;
 $GLOBALS['SQL_DROP_TABLES'] = <<<'SQL'
 $GLOBALS['SQL_DROP_TABLES'] = <<<'SQL'
 DROP TABLE IF EXISTS `_entrytag`, `_tag`, `_entrytmp`, `_entry`, `_feed`, `_category`;
 DROP TABLE IF EXISTS `_entrytag`, `_tag`, `_entrytmp`, `_entry`, `_feed`, `_category`;
 SQL;
 SQL;
+
+$GLOBALS['SQL_UPDATE_YEAR_2038'] = <<<'SQL'
+ALTER TABLE `_entry`	-- v1.23
+	MODIFY COLUMN `date` BIGINT,
+	MODIFY COLUMN `lastSeen` BIGINT DEFAULT 0;
+ALTER TABLE `_entrytmp`
+	MODIFY COLUMN `date` BIGINT,
+	MODIFY COLUMN `lastSeen` BIGINT DEFAULT 0;
+ALTER TABLE `_feed`
+	MODIFY COLUMN `lastUpdate` BIGINT DEFAULT 0;
+SQL;

+ 16 - 5
app/SQL/install.sql.pgsql.php

@@ -21,7 +21,7 @@ CREATE TABLE IF NOT EXISTS `_feed` (
 	"name" VARCHAR(191) NOT NULL,
 	"name" VARCHAR(191) NOT NULL,
 	"website" VARCHAR(32768),
 	"website" VARCHAR(32768),
 	"description" TEXT,
 	"description" TEXT,
-	"lastUpdate" INT DEFAULT 0,
+	"lastUpdate" BIGINT DEFAULT 0,
 	"priority" SMALLINT NOT NULL DEFAULT 10,
 	"priority" SMALLINT NOT NULL DEFAULT 10,
 	"pathEntries" VARCHAR(65535) DEFAULT NULL,
 	"pathEntries" VARCHAR(65535) DEFAULT NULL,
 	"httpAuth" VARCHAR(1024) DEFAULT NULL,
 	"httpAuth" VARCHAR(1024) DEFAULT NULL,
@@ -42,8 +42,8 @@ CREATE TABLE IF NOT EXISTS `_entry` (
 	"author" VARCHAR(65535),
 	"author" VARCHAR(65535),
 	"content" TEXT,
 	"content" TEXT,
 	"link" VARCHAR(32768) NOT NULL,
 	"link" VARCHAR(32768) NOT NULL,
-	"date" INT,
-	"lastSeen" INT DEFAULT 0,
+	"date" BIGINT,
+	"lastSeen" BIGINT DEFAULT 0,
 	"hash" BYTEA,
 	"hash" BYTEA,
 	"is_read" SMALLINT NOT NULL DEFAULT 0,
 	"is_read" SMALLINT NOT NULL DEFAULT 0,
 	"is_favorite" SMALLINT NOT NULL DEFAULT 0,
 	"is_favorite" SMALLINT NOT NULL DEFAULT 0,
@@ -70,8 +70,8 @@ CREATE TABLE IF NOT EXISTS `_entrytmp` (	-- v1.7
 	"author" VARCHAR(65535),
 	"author" VARCHAR(65535),
 	"content" TEXT,
 	"content" TEXT,
 	"link" VARCHAR(32768) NOT NULL,
 	"link" VARCHAR(32768) NOT NULL,
-	"date" INT,
-	"lastSeen" INT DEFAULT 0,
+	"date" BIGINT,
+	"lastSeen" BIGINT DEFAULT 0,
 	"hash" BYTEA,
 	"hash" BYTEA,
 	"is_read" SMALLINT NOT NULL DEFAULT 0,
 	"is_read" SMALLINT NOT NULL DEFAULT 0,
 	"is_favorite" SMALLINT NOT NULL DEFAULT 0,
 	"is_favorite" SMALLINT NOT NULL DEFAULT 0,
@@ -101,3 +101,14 @@ SQL;
 $GLOBALS['SQL_DROP_TABLES'] = <<<'SQL'
 $GLOBALS['SQL_DROP_TABLES'] = <<<'SQL'
 DROP TABLE IF EXISTS `_entrytag`, `_tag`, `_entrytmp`, `_entry`, `_feed`, `_category`;
 DROP TABLE IF EXISTS `_entrytag`, `_tag`, `_entrytmp`, `_entry`, `_feed`, `_category`;
 SQL;
 SQL;
+
+$GLOBALS['SQL_UPDATE_YEAR_2038'] = <<<'SQL'
+ALTER TABLE `_entry`	-- v1.23
+	ALTER COLUMN "date" SET DATA TYPE BIGINT,
+	ALTER COLUMN "lastSeen" SET DATA TYPE BIGINT;
+ALTER TABLE `_entrytmp`
+	ALTER COLUMN "date" SET DATA TYPE BIGINT,
+	ALTER COLUMN "lastSeen" SET DATA TYPE BIGINT;
+ALTER TABLE `_feed`
+	ALTER COLUMN "lastUpdate" SET DATA TYPE BIGINT;
+SQL;

+ 5 - 5
app/SQL/install.sql.sqlite.php

@@ -22,7 +22,7 @@ CREATE TABLE IF NOT EXISTS `feed` (
 	`name` VARCHAR(191) NOT NULL,
 	`name` VARCHAR(191) NOT NULL,
 	`website` VARCHAR(32768),
 	`website` VARCHAR(32768),
 	`description` TEXT,
 	`description` TEXT,
-	`lastUpdate` INT(11) DEFAULT 0,	-- Until year 2038
+	`lastUpdate` BIGINT DEFAULT 0,
 	`priority` TINYINT(2) NOT NULL DEFAULT 10,
 	`priority` TINYINT(2) NOT NULL DEFAULT 10,
 	`pathEntries` VARCHAR(65535) DEFAULT NULL,
 	`pathEntries` VARCHAR(65535) DEFAULT NULL,
 	`httpAuth` VARCHAR(1024) DEFAULT NULL,
 	`httpAuth` VARCHAR(1024) DEFAULT NULL,
@@ -43,8 +43,8 @@ CREATE TABLE IF NOT EXISTS `entry` (
 	`author` VARCHAR(65535),
 	`author` VARCHAR(65535),
 	`content` TEXT,
 	`content` TEXT,
 	`link` VARCHAR(32768) NOT NULL,
 	`link` VARCHAR(32768) NOT NULL,
-	`date` INT(11),	-- Until year 2038
-	`lastSeen` INT(11) DEFAULT 0,	-- v1.1.1, Until year 2038
+	`date` BIGINT,
+	`lastSeen` BIGINT DEFAULT 0,
 	`hash` BINARY(16),	-- v1.1.1
 	`hash` BINARY(16),	-- v1.1.1
 	`is_read` BOOLEAN NOT NULL DEFAULT 0,
 	`is_read` BOOLEAN NOT NULL DEFAULT 0,
 	`is_favorite` BOOLEAN NOT NULL DEFAULT 0,
 	`is_favorite` BOOLEAN NOT NULL DEFAULT 0,
@@ -69,8 +69,8 @@ CREATE TABLE IF NOT EXISTS `entrytmp` (	-- v1.7
 	`author` VARCHAR(65535),
 	`author` VARCHAR(65535),
 	`content` TEXT,
 	`content` TEXT,
 	`link` VARCHAR(32768) NOT NULL,
 	`link` VARCHAR(32768) NOT NULL,
-	`date` INT(11),
-	`lastSeen` INT(11) DEFAULT 0,
+	`date` BIGINT,
+	`lastSeen` BIGINT DEFAULT 0,
 	`hash` BINARY(16),
 	`hash` BINARY(16),
 	`is_read` BOOLEAN NOT NULL DEFAULT 0,
 	`is_read` BOOLEAN NOT NULL DEFAULT 0,
 	`is_favorite` BOOLEAN NOT NULL DEFAULT 0,
 	`is_favorite` BOOLEAN NOT NULL DEFAULT 0,