aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Alexandre Alapetite <alexandre@alapetite.fr> 2017-03-26 00:01:11 +0100
committerGravatar Alexandre Alapetite <alexandre@alapetite.fr> 2017-03-26 00:01:11 +0100
commit22b41f3bfcbd5a54d59789c2cebfda6dc23b7dde (patch)
tree791c68ecdf3b5fb6816ab82eaed5ce454a81e4dc
parenta513ca9030314dec0f01b3cc147ceaf0c9b14d88 (diff)
Candidate implementation of defered insertion
https://github.com/FreshRSS/FreshRSS/issues/530
-rwxr-xr-xapp/Controllers/feedController.php8
-rw-r--r--app/Controllers/importExportController.php1
-rw-r--r--app/Models/EntryDAO.php115
-rw-r--r--app/Models/EntryDAOPGSQL.php26
-rw-r--r--app/Models/EntryDAOSQLite.php39
-rw-r--r--app/Models/UserDAO.php10
-rw-r--r--app/SQL/install.sql.mysql.php23
-rw-r--r--app/SQL/install.sql.pgsql.php24
-rw-r--r--app/SQL/install.sql.sqlite.php24
-rw-r--r--app/install.php36
-rw-r--r--p/scripts/main.js1
11 files changed, 234 insertions, 73 deletions
diff --git a/app/Controllers/feedController.php b/app/Controllers/feedController.php
index f71f26a4e..a2d9d5c35 100755
--- a/app/Controllers/feedController.php
+++ b/app/Controllers/feedController.php
@@ -226,7 +226,7 @@ class FreshRSS_feed_Controller extends Minz_ActionController {
}
}
- public static function actualizeFeed($feed_id, $feed_url, $force, $simplePiePush = null, $isNewFeed = false) {
+ public static function actualizeFeed($feed_id, $feed_url, $force, $simplePiePush = null, $isNewFeed = false, $noCommit = false) {
@set_time_limit(300);
$feedDAO = FreshRSS_Factory::createFeedDao();
@@ -434,6 +434,9 @@ class FreshRSS_feed_Controller extends Minz_ActionController {
break;
}
}
+ if (!$noCommit) {
+ $entryDAO->commitNewEntries();
+ }
return array($updated_feeds, reset($feeds));
}
@@ -452,8 +455,9 @@ class FreshRSS_feed_Controller extends Minz_ActionController {
$id = Minz_Request::param('id');
$url = Minz_Request::param('url');
$force = Minz_Request::param('force');
+ $noCommit = Minz_Session::param('isLastFeed', 1) != 1;
- list($updated_feeds, $feed) = self::actualizeFeed($id, $url, $force);
+ list($updated_feeds, $feed) = self::actualizeFeed($id, $url, $force, null, false, $noCommit);
if (Minz_Request::param('ajax')) {
// Most of the time, ajax request is for only one feed. But since
diff --git a/app/Controllers/importExportController.php b/app/Controllers/importExportController.php
index 6ae89defb..ededfe506 100644
--- a/app/Controllers/importExportController.php
+++ b/app/Controllers/importExportController.php
@@ -475,6 +475,7 @@ class FreshRSS_importExport_Controller extends Minz_ActionController {
}
}
$this->entryDAO->commit();
+ $entryDAO->commitNewEntries();
return !$error;
}
diff --git a/app/Models/EntryDAO.php b/app/Models/EntryDAO.php
index afcde3d7f..decae9307 100644
--- a/app/Models/EntryDAO.php
+++ b/app/Models/EntryDAO.php
@@ -88,6 +88,38 @@ class FreshRSS_EntryDAO extends Minz_ModelPdo implements FreshRSS_Searchable {
return false;
}
+ protected function createEntryTempTable() {
+ $ok = false;
+ $hadTransaction = $this->bd->inTransaction();
+ if ($hadTransaction) {
+ $this->bd->commit();
+ }
+ try {
+ $db = FreshRSS_Context::$system_conf->db;
+ require_once(APP_PATH . '/SQL/install.sql.' . $db['type'] . '.php');
+ Minz_Log::warning('SQL CREATE TABLE entrytmp...');
+ if (defined('SQL_CREATE_TABLE_ENTRYTMP')) {
+ $sql = sprintf(SQL_CREATE_TABLE_ENTRYTMP, $this->prefix);
+ $stm = $this->bd->prepare($sql);
+ $ok = $stm && $stm->execute();
+ } else {
+ global $SQL_CREATE_TABLE_ENTRYTMP;
+ $ok = !empty($SQL_CREATE_TABLE_ENTRYTMP);
+ foreach ($SQL_CREATE_TABLE_ENTRYTMP as $instruction) {
+ $sql = sprintf($instruction, $this->prefix);
+ $stm = $this->bd->prepare($sql);
+ $ok &= $stm && $stm->execute();
+ }
+ }
+ } catch (Exception $e) {
+ Minz_Log::error('FreshRSS_EntryDAO::createEntryTempTable error: ' . $e->getMessage());
+ }
+ if ($hadTransaction) {
+ $this->bd->beginTransaction();
+ }
+ return $ok;
+ }
+
protected function autoUpdateDb($errorInfo) {
if (isset($errorInfo[0])) {
if ($errorInfo[0] === '42S22') { //ER_BAD_FIELD_ERROR
@@ -97,6 +129,8 @@ class FreshRSS_EntryDAO extends Minz_ModelPdo implements FreshRSS_Searchable {
return $this->addColumn($column);
}
}
+ } elseif ($errorInfo[0] === '42S02' && stripos($errorInfo[2], 'entrytmp') !== false) { //ER_BAD_TABLE_ERROR
+ return $this->createEntryTempTable(); //v1.7
}
}
if (isset($errorInfo[1])) {
@@ -110,8 +144,8 @@ class FreshRSS_EntryDAO extends Minz_ModelPdo implements FreshRSS_Searchable {
private $addEntryPrepared = null;
public function addEntry($valuesTmp) {
- if ($this->addEntryPrepared === null) {
- $sql = 'INSERT INTO `' . $this->prefix . 'entry` (id, guid, title, author, '
+ if ($this->addEntryPrepared == null) {
+ $sql = 'INSERT INTO `' . $this->prefix . 'entrytmp` (id, guid, title, author, '
. ($this->isCompressed() ? 'content_bin' : 'content')
. ', link, date, `lastSeen`, hash, is_read, is_favorite, id_feed, tags) '
. 'VALUES(:id, :guid, :title, :author, '
@@ -121,41 +155,43 @@ class FreshRSS_EntryDAO extends Minz_ModelPdo implements FreshRSS_Searchable {
. ', :is_read, :is_favorite, :id_feed, :tags)';
$this->addEntryPrepared = $this->bd->prepare($sql);
}
- $this->addEntryPrepared->bindParam(':id', $valuesTmp['id']);
- $valuesTmp['guid'] = substr($valuesTmp['guid'], 0, 760);
- $valuesTmp['guid'] = safe_ascii($valuesTmp['guid']);
- $this->addEntryPrepared->bindParam(':guid', $valuesTmp['guid']);
- $valuesTmp['title'] = substr($valuesTmp['title'], 0, 255);
- $this->addEntryPrepared->bindParam(':title', $valuesTmp['title']);
- $valuesTmp['author'] = substr($valuesTmp['author'], 0, 255);
- $this->addEntryPrepared->bindParam(':author', $valuesTmp['author']);
- $this->addEntryPrepared->bindParam(':content', $valuesTmp['content']);
- $valuesTmp['link'] = substr($valuesTmp['link'], 0, 1023);
- $valuesTmp['link'] = safe_ascii($valuesTmp['link']);
- $this->addEntryPrepared->bindParam(':link', $valuesTmp['link']);
- $this->addEntryPrepared->bindParam(':date', $valuesTmp['date'], PDO::PARAM_INT);
- $valuesTmp['lastSeen'] = time();
- $this->addEntryPrepared->bindParam(':last_seen', $valuesTmp['lastSeen'], PDO::PARAM_INT);
- $valuesTmp['is_read'] = $valuesTmp['is_read'] ? 1 : 0;
- $this->addEntryPrepared->bindParam(':is_read', $valuesTmp['is_read'], PDO::PARAM_INT);
- $valuesTmp['is_favorite'] = $valuesTmp['is_favorite'] ? 1 : 0;
- $this->addEntryPrepared->bindParam(':is_favorite', $valuesTmp['is_favorite'], PDO::PARAM_INT);
- $this->addEntryPrepared->bindParam(':id_feed', $valuesTmp['id_feed'], PDO::PARAM_INT);
- $valuesTmp['tags'] = substr($valuesTmp['tags'], 0, 1023);
- $this->addEntryPrepared->bindParam(':tags', $valuesTmp['tags']);
-
- if ($this->hasNativeHex()) {
- $this->addEntryPrepared->bindParam(':hash', $valuesTmp['hash']);
- } else {
- $valuesTmp['hashBin'] = pack('H*', $valuesTmp['hash']); //hex2bin() is PHP5.4+
- $this->addEntryPrepared->bindParam(':hash', $valuesTmp['hashBin']);
+ if ($this->addEntryPrepared) {
+ $this->addEntryPrepared->bindParam(':id', $valuesTmp['id']);
+ $valuesTmp['guid'] = substr($valuesTmp['guid'], 0, 760);
+ $valuesTmp['guid'] = safe_ascii($valuesTmp['guid']);
+ $this->addEntryPrepared->bindParam(':guid', $valuesTmp['guid']);
+ $valuesTmp['title'] = substr($valuesTmp['title'], 0, 255);
+ $this->addEntryPrepared->bindParam(':title', $valuesTmp['title']);
+ $valuesTmp['author'] = substr($valuesTmp['author'], 0, 255);
+ $this->addEntryPrepared->bindParam(':author', $valuesTmp['author']);
+ $this->addEntryPrepared->bindParam(':content', $valuesTmp['content']);
+ $valuesTmp['link'] = substr($valuesTmp['link'], 0, 1023);
+ $valuesTmp['link'] = safe_ascii($valuesTmp['link']);
+ $this->addEntryPrepared->bindParam(':link', $valuesTmp['link']);
+ $this->addEntryPrepared->bindParam(':date', $valuesTmp['date'], PDO::PARAM_INT);
+ $valuesTmp['lastSeen'] = time();
+ $this->addEntryPrepared->bindParam(':last_seen', $valuesTmp['lastSeen'], PDO::PARAM_INT);
+ $valuesTmp['is_read'] = $valuesTmp['is_read'] ? 1 : 0;
+ $this->addEntryPrepared->bindParam(':is_read', $valuesTmp['is_read'], PDO::PARAM_INT);
+ $valuesTmp['is_favorite'] = $valuesTmp['is_favorite'] ? 1 : 0;
+ $this->addEntryPrepared->bindParam(':is_favorite', $valuesTmp['is_favorite'], PDO::PARAM_INT);
+ $this->addEntryPrepared->bindParam(':id_feed', $valuesTmp['id_feed'], PDO::PARAM_INT);
+ $valuesTmp['tags'] = substr($valuesTmp['tags'], 0, 1023);
+ $this->addEntryPrepared->bindParam(':tags', $valuesTmp['tags']);
+
+ if ($this->hasNativeHex()) {
+ $this->addEntryPrepared->bindParam(':hash', $valuesTmp['hash']);
+ } else {
+ $valuesTmp['hashBin'] = pack('H*', $valuesTmp['hash']); //hex2bin() is PHP5.4+
+ $this->addEntryPrepared->bindParam(':hash', $valuesTmp['hashBin']);
+ }
}
-
if ($this->addEntryPrepared && $this->addEntryPrepared->execute()) {
return $this->bd->lastInsertId();
} else {
$info = $this->addEntryPrepared == null ? array(0 => '', 1 => '', 2 => 'syntax error') : $this->addEntryPrepared->errorInfo();
if ($this->autoUpdateDb($info)) {
+ $this->addEntryPrepared = null;
return $this->addEntry($valuesTmp);
} elseif ((int)($info[0] / 1000) !== 23) { //Filter out "SQLSTATE Class code 23: Constraint Violation" because of expected duplicate entries
Minz_Log::error('SQL error addEntry: ' . $info[0] . ': ' . $info[1] . ' ' . $info[2]
@@ -165,6 +201,23 @@ class FreshRSS_EntryDAO extends Minz_ModelPdo implements FreshRSS_Searchable {
}
}
+ public function commitNewEntries() {
+ $sql = 'SET @rank=SELECT MAX(id) - COUNT(*) FROM `' . $this->prefix . 'entrytmp`; ' . //MySQL-specific
+ 'INSERT IGNORE INTO `' . $this->prefix . 'entry` (id, guid, title, author, content_bin, link, date, `lastSeen`, hash, is_read, is_favorite, id_feed, tags) ' .
+ 'SELECT @rank:=@rank+1 AS id, guid, title, author, content_bin, link, date, `lastSeen`, hash, is_read, is_favorite, id_feed, tags FROM `' . $this->prefix . 'entrytmp` ORDER BY date; ' .
+ 'DELETE FROM `' . $this->prefix . 'entrytmp` WHERE id <= @rank;';
+ $stm = $this->bd->prepare($sql);
+ $hadTransaction = $this->bd->inTransaction();
+ if (!$hadTransaction) {
+ $this->bd->beginTransaction();
+ }
+ $result = $stm ? $stm->execute() : false;
+ if (!$hadTransaction) {
+ $this->bd->commit();
+ }
+ return $result;
+ }
+
private $updateEntryPrepared = null;
public function updateEntry($valuesTmp) {
diff --git a/app/Models/EntryDAOPGSQL.php b/app/Models/EntryDAOPGSQL.php
index b96a62ebc..b25993c47 100644
--- a/app/Models/EntryDAOPGSQL.php
+++ b/app/Models/EntryDAOPGSQL.php
@@ -11,6 +11,11 @@ class FreshRSS_EntryDAOPGSQL extends FreshRSS_EntryDAOSQLite {
}
protected function autoUpdateDb($errorInfo) {
+ if (isset($errorInfo[0])) {
+ if ($errorInfo[0] === '42P01' && stripos($errorInfo[2], 'entrytmp') !== false) { //undefined_table
+ return $this->createEntryTempTable();
+ }
+ }
return false;
}
@@ -18,6 +23,27 @@ class FreshRSS_EntryDAOPGSQL extends FreshRSS_EntryDAOSQLite {
return false;
}
+ public function commitNewEntries() {
+ $sql = 'DO $$
+DECLARE
+maxrank bigint := (SELECT MAX(id) FROM `' . $this->prefix . 'entrytmp`);
+rank bigint := (SELECT maxrank - COUNT(*) FROM `' . $this->prefix . 'entrytmp`);
+BEGIN
+ INSERT INTO `' . $this->prefix . 'entry` (id, guid, title, author, content, link, date, `lastSeen`, hash, is_read, is_favorite, id_feed, tags)
+ (SELECT rank + row_number() OVER(ORDER BY date) AS id, guid, title, author, content, link, date, `lastSeen`, hash, is_read, is_favorite, id_feed, tags FROM `' . $this->prefix . 'entrytmp` ORDER BY date);
+ DELETE FROM `' . $this->prefix . 'entrytmp` WHERE id <= maxrank;
+END $$;';
+ $hadTransaction = $this->bd->inTransaction();
+ if (!$hadTransaction) {
+ $this->bd->beginTransaction();
+ }
+ $result = $this->bd->exec($sql) !== false;
+ if (!$hadTransaction) {
+ $this->bd->commit();
+ }
+ return $result;
+ }
+
public function size($all = true) {
$db = FreshRSS_Context::$system_conf->db;
$sql = 'SELECT pg_size_pretty(pg_database_size(?))';
diff --git a/app/Models/EntryDAOSQLite.php b/app/Models/EntryDAOSQLite.php
index 34e854608..ad7bcd865 100644
--- a/app/Models/EntryDAOSQLite.php
+++ b/app/Models/EntryDAOSQLite.php
@@ -7,21 +7,42 @@ class FreshRSS_EntryDAOSQLite extends FreshRSS_EntryDAO {
}
protected function autoUpdateDb($errorInfo) {
- if (empty($errorInfo[0]) || $errorInfo[0] == '42S22') { //ER_BAD_FIELD_ERROR
- //autoAddColumn
- if ($tableInfo = $this->bd->query("SELECT sql FROM sqlite_master where name='entry'")) {
- $showCreate = $tableInfo->fetchColumn();
- Minz_Log::debug('FreshRSS_EntryDAOSQLite::autoUpdateDb: ' . $showCreate);
- foreach (array('lastSeen', 'hash') as $column) {
- if (stripos($showCreate, $column) === false) {
- return $this->addColumn($column);
- }
+ Minz_Log::error('FreshRSS_EntryDAO::autoUpdateDb error: ' . print_r($errorInfo, true));
+ if ($tableInfo = $this->bd->query("SELECT sql FROM sqlite_master where name='entrytmp'")) {
+ $showCreate = $tableInfo->fetchColumn();
+ if (stripos($showCreate, 'entrytmp') === false) {
+ return $this->createEntryTempTable();
+ }
+ }
+ if ($tableInfo = $this->bd->query("SELECT sql FROM sqlite_master where name='entry'")) {
+ $showCreate = $tableInfo->fetchColumn();
+ foreach (array('lastSeen', 'hash') as $column) {
+ if (stripos($showCreate, $column) === false) {
+ return $this->addColumn($column);
}
}
}
return false;
}
+ public function commitNewEntries() {
+ $sql = '
+CREATE TEMP TABLE `tmp` AS SELECT id, guid, title, author, content, link, date, `lastSeen`, hash, is_read, is_favorite, id_feed, tags FROM `' . $this->prefix . 'entrytmp` ORDER BY date;
+INSERT OR IGNORE INTO `' . $this->prefix . 'entry` (id, guid, title, author, content, link, date, `lastSeen`, hash, is_read, is_favorite, id_feed, tags)
+ SELECT rowid + (SELECT MAX(id) - COUNT(*) FROM `tmp`) AS id, guid, title, author, content, link, date, `lastSeen`, hash, is_read, is_favorite, id_feed, tags FROM `tmp` ORDER BY date;
+DELETE FROM `' . $this->prefix . 'entrytmp` WHERE id <= (SELECT MAX(id) FROM `tmp`);
+DROP TABLE `tmp`;';
+ $hadTransaction = $this->bd->inTransaction();
+ if (!$hadTransaction) {
+ $this->bd->beginTransaction();
+ }
+ $result = $this->bd->exec($sql) !== false;
+ if (!$hadTransaction) {
+ $this->bd->commit();
+ }
+ return $result;
+ }
+
protected function sqlConcat($s1, $s2) {
return $s1 . '||' . $s2;
}
diff --git a/app/Models/UserDAO.php b/app/Models/UserDAO.php
index a60caf395..310c7c096 100644
--- a/app/Models/UserDAO.php
+++ b/app/Models/UserDAO.php
@@ -14,21 +14,23 @@ class FreshRSS_UserDAO extends Minz_ModelPdo {
$ok = false;
$bd_prefix_user = $db['prefix'] . $username . '_';
if (defined('SQL_CREATE_TABLES')) { //E.g. MySQL
- $sql = sprintf(SQL_CREATE_TABLES, $bd_prefix_user, _t('gen.short.default_category'));
+ $sql = sprintf(SQL_CREATE_TABLES . SQL_CREATE_TABLE_ENTRYTMP, $bd_prefix_user, _t('gen.short.default_category'));
$stm = $userPDO->bd->prepare($sql);
$ok = $stm && $stm->execute();
} else { //E.g. SQLite
global $SQL_CREATE_TABLES;
+ global $SQL_CREATE_TABLE_ENTRYTMP;
if (is_array($SQL_CREATE_TABLES)) {
- $ok = true;
- foreach ($SQL_CREATE_TABLES as $instruction) {
+ $instructions = array_merge($SQL_CREATE_TABLES, $SQL_CREATE_TABLE_ENTRYTMP);
+ $ok = !empty($instructions);
+ foreach ($instructions as $instruction) {
$sql = sprintf($instruction, $bd_prefix_user, _t('gen.short.default_category'));
$stm = $userPDO->bd->prepare($sql);
$ok &= ($stm && $stm->execute());
}
}
}
- if ($insertDefaultFeeds) {
+ if ($ok && $insertDefaultFeeds) {
if (defined('SQL_INSERT_FEEDS')) { //E.g. MySQL
$sql = sprintf(SQL_INSERT_FEEDS, $bd_prefix_user);
$stm = $userPDO->bd->prepare($sql);
diff --git a/app/SQL/install.sql.mysql.php b/app/SQL/install.sql.mysql.php
index a454829d5..ceca07f93 100644
--- a/app/SQL/install.sql.mysql.php
+++ b/app/SQL/install.sql.mysql.php
@@ -61,6 +61,29 @@ ENGINE = INNODB;
INSERT IGNORE INTO `%1$scategory` (id, name) VALUES(1, "%2$s");
');
+define('SQL_CREATE_TABLE_ENTRYTMP', '
+CREATE TABLE IF NOT EXISTS `%1$sentrytmp` ( -- v1.7
+ `id` bigint NOT NULL,
+ `guid` varchar(760) CHARACTER SET latin1 NOT NULL,
+ `title` varchar(255) NOT NULL,
+ `author` varchar(255),
+ `content_bin` blob,
+ `link` varchar(1023) CHARACTER SET latin1 NOT NULL,
+ `date` int(11),
+ `lastSeen` INT(11) DEFAULT 0,
+ `hash` BINARY(16),
+ `is_read` boolean NOT NULL DEFAULT 0,
+ `is_favorite` boolean NOT NULL DEFAULT 0,
+ `id_feed` SMALLINT,
+ `tags` varchar(1023),
+ PRIMARY KEY (`id`),
+ FOREIGN KEY (`id_feed`) REFERENCES `%1$sfeed`(`id`) ON DELETE CASCADE ON UPDATE CASCADE,
+ UNIQUE KEY (`id_feed`,`guid`),
+ INDEX (`date`),
+) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci
+ENGINE = INNODB;
+');
+
define('SQL_INSERT_FEEDS', '
INSERT IGNORE INTO `%1$sfeed` (url, category, name, website, description, ttl) VALUES("http://freshrss.org/feeds/all.atom.xml", 1, "FreshRSS.org", "http://freshrss.org/", "FreshRSS, a free, self-hostable aggregator…", 86400);
INSERT IGNORE INTO `%1$sfeed` (url, category, name, website, description, ttl) VALUES("https://github.com/FreshRSS/FreshRSS/releases.atom", 1, "FreshRSS @ GitHub", "https://github.com/FreshRSS/FreshRSS/", "FreshRSS releases @ GitHub", 86400);
diff --git a/app/SQL/install.sql.pgsql.php b/app/SQL/install.sql.pgsql.php
index 9f4240b98..1a666cb8a 100644
--- a/app/SQL/install.sql.pgsql.php
+++ b/app/SQL/install.sql.pgsql.php
@@ -32,7 +32,7 @@ $SQL_CREATE_TABLES = array(
'CREATE TABLE IF NOT EXISTS "%1$sentry" (
"id" BIGINT NOT NULL PRIMARY KEY,
- "guid" VARCHAR(760) UNIQUE NOT NULL,
+ "guid" VARCHAR(760) NOT NULL,
"title" VARCHAR(255) NOT NULL,
"author" VARCHAR(255),
"content" TEXT,
@@ -54,6 +54,28 @@ $SQL_CREATE_TABLES = array(
'INSERT INTO "%1$scategory" (name) SELECT \'%2$s\' WHERE NOT EXISTS (SELECT id FROM "%1$scategory" WHERE id = 1);',
);
+global $SQL_CREATE_TABLE_ENTRYTMP;
+$SQL_CREATE_TABLE_ENTRYTMP = array(
+'CREATE TABLE IF NOT EXISTS "%1$sentrytmp" ( -- v1.7
+ "id" BIGINT NOT NULL PRIMARY KEY,
+ "guid" VARCHAR(760) NOT NULL,
+ "title" VARCHAR(255) NOT NULL,
+ "author" VARCHAR(255),
+ "content" TEXT,
+ "link" VARCHAR(1023) NOT NULL,
+ "date" INT,
+ "lastSeen" INT DEFAULT 0,
+ "hash" BYTEA,
+ "is_read" SMALLINT NOT NULL DEFAULT 0,
+ "is_favorite" SMALLINT NOT NULL DEFAULT 0,
+ "id_feed" SMALLINT,
+ "tags" VARCHAR(1023),
+ FOREIGN KEY ("id_feed") REFERENCES "%1$sfeed" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
+ UNIQUE ("id_feed","guid")
+);',
+'CREATE INDEX %1$sentrytmp_date_index ON "%1$sentrytmp" ("date");',
+);
+
global $SQL_INSERT_FEEDS;
$SQL_INSERT_FEEDS = array(
'INSERT INTO "%1$sfeed" (url, category, name, website, description, ttl) SELECT \'http://freshrss.org/feeds/all.atom.xml\', 1, \'FreshRSS.org\', \'http://freshrss.org/\', \'FreshRSS, a free, self-hostable aggregator…\', 86400 WHERE NOT EXISTS (SELECT id FROM "%1$sfeed" WHERE url = \'http://freshrss.org/feeds/all.atom.xml\');',
diff --git a/app/SQL/install.sql.sqlite.php b/app/SQL/install.sql.sqlite.php
index 68d93ba92..ad7d525fd 100644
--- a/app/SQL/install.sql.sqlite.php
+++ b/app/SQL/install.sql.sqlite.php
@@ -57,6 +57,30 @@ $SQL_CREATE_TABLES = array(
'INSERT OR IGNORE INTO `category` (id, name) VALUES(1, "%2$s");',
);
+global $SQL_CREATE_TABLE_ENTRYTMP;
+$SQL_CREATE_TABLE_ENTRYTMP = array(
+'CREATE TABLE IF NOT EXISTS `entrytmp` ( -- v1.7
+ `id` bigint NOT NULL,
+ `guid` varchar(760) NOT NULL,
+ `title` varchar(255) NOT NULL,
+ `author` varchar(255),
+ `content` text,
+ `link` varchar(1023) NOT NULL,
+ `date` int(11),
+ `lastSeen` INT(11) DEFAULT 0,
+ `hash` BINARY(16),
+ `is_read` boolean NOT NULL DEFAULT 0,
+ `is_favorite` boolean NOT NULL DEFAULT 0,
+ `id_feed` SMALLINT,
+ `tags` varchar(1023),
+ PRIMARY KEY (`id`),
+ FOREIGN KEY (`id_feed`) REFERENCES `feed`(`id`) ON DELETE CASCADE ON UPDATE CASCADE,
+ UNIQUE (`id_feed`,`guid`)
+);',
+
+'CREATE INDEX IF NOT EXISTS entrytmp_date_index ON `entrytmp`(`date`);',
+);
+
global $SQL_INSERT_FEEDS;
$SQL_INSERT_FEEDS = array(
'INSERT OR IGNORE INTO `feed` (url, category, name, website, description, ttl) VALUES("http://freshrss.org/feeds/all.atom.xml", 1, "FreshRSS.org", "http://freshrss.org/", "FreshRSS, a free, self-hostable aggregator…", 86400);',
diff --git a/app/install.php b/app/install.php
index 9a88e0f37..17037c384 100644
--- a/app/install.php
+++ b/app/install.php
@@ -342,35 +342,19 @@ function checkDbUser(&$dbOptions) {
$driver_options = $dbOptions['options'];
try {
$c = new PDO($str, $dbOptions['user'], $dbOptions['password'], $driver_options);
-
if (defined('SQL_CREATE_TABLES')) {
- $sql = sprintf(SQL_CREATE_TABLES, $dbOptions['prefix_user'], _t('gen.short.default_category'));
- $stm = $c->prepare($sql);
- $ok = $stm->execute();
- } else {
- global $SQL_CREATE_TABLES;
- if (is_array($SQL_CREATE_TABLES)) {
- $ok = true;
- foreach ($SQL_CREATE_TABLES as $instruction) {
- $sql = sprintf($instruction, $dbOptions['prefix_user'], _t('gen.short.default_category'));
- $stm = $c->prepare($sql);
- $ok &= $stm->execute();
- }
- }
- }
-
- if (defined('SQL_INSERT_FEEDS')) {
- $sql = sprintf(SQL_INSERT_FEEDS, $dbOptions['prefix_user']);
+ $sql = sprintf(SQL_CREATE_TABLES . SQL_CREATE_TABLE_ENTRYTMP . SQL_INSERT_FEEDS,
+ $dbOptions['prefix_user'], _t('gen.short.default_category'));
$stm = $c->prepare($sql);
- $ok &= $stm->execute();
+ $ok = $stm && $stm->execute();
} else {
- global $SQL_INSERT_FEEDS;
- if (is_array($SQL_INSERT_FEEDS)) {
- foreach ($SQL_INSERT_FEEDS as $instruction) {
- $sql = sprintf($instruction, $dbOptions['prefix_user']);
- $stm = $c->prepare($sql);
- $ok &= $stm->execute();
- }
+ global $SQL_CREATE_TABLES, $SQL_CREATE_TABLE_ENTRYTMP, $SQL_INSERT_FEEDS;
+ $instructions = array_merge($SQL_CREATE_TABLES, $SQL_CREATE_TABLE_ENTRYTMP, $SQL_INSERT_FEEDS);
+ $ok = !empty($instructions);
+ foreach ($instructions as $instruction) {
+ $sql = sprintf($instruction, $dbOptions['prefix_user'], _t('gen.short.default_category'));
+ $stm = $c->prepare($sql);
+ $ok &= $stm && $stm->execute();
}
}
} catch (PDOException $e) {
diff --git a/p/scripts/main.js b/p/scripts/main.js
index 5dbb95c91..c2f60bf7f 100644
--- a/p/scripts/main.js
+++ b/p/scripts/main.js
@@ -809,6 +809,7 @@ function updateFeed(feeds, feeds_count) {
url: feed.url,
data : {
_csrf: context.csrf,
+ isLastFeed: feeds.length <= 0 ? 1 : 0,
},
}).always(function (data) {
feed_processed++;