|
|
@@ -6,38 +6,48 @@ class FreshRSS_EntryDAO extends Minz_ModelPdo implements FreshRSS_Searchable {
|
|
|
return parent::$sharedDbType !== 'sqlite';
|
|
|
}
|
|
|
|
|
|
- protected function autoAddColumn($errorInfo) {
|
|
|
- if (isset($errorInfo[0])) {
|
|
|
- if ($errorInfo[0] == '42S22') { //ER_BAD_FIELD_ERROR
|
|
|
- $hasTransaction = false;
|
|
|
- try {
|
|
|
- $stm = null;
|
|
|
- if (stripos($errorInfo[2], 'lastSeen') !== false) { //v1.2
|
|
|
- if (!$this->bd->inTransaction()) {
|
|
|
- $this->bd->beginTransaction();
|
|
|
- $hasTransaction = true;
|
|
|
- }
|
|
|
- $stm = $this->bd->prepare('ALTER TABLE `' . $this->prefix . 'entry` ADD COLUMN lastSeen INT(11) NOT NULL');
|
|
|
- if ($stm && $stm->execute()) {
|
|
|
- $stm = $this->bd->prepare('CREATE INDEX entry_lastSeen_index ON `' . $this->prefix . 'entry`(`lastSeen`);'); //"IF NOT EXISTS" does not exist in MySQL 5.7
|
|
|
- if ($stm && $stm->execute()) {
|
|
|
- if ($hasTransaction) {
|
|
|
- $this->bd->commit();
|
|
|
- }
|
|
|
- return true;
|
|
|
- }
|
|
|
- }
|
|
|
+ protected function addColumn($name) {
|
|
|
+ Minz_Log::debug('FreshRSS_EntryDAO::autoAddColumn: ' . $name);
|
|
|
+ $hasTransaction = false;
|
|
|
+ try {
|
|
|
+ $stm = null;
|
|
|
+ if ($name === 'lastSeen') { //v1.2
|
|
|
+ if (!$this->bd->inTransaction()) {
|
|
|
+ $this->bd->beginTransaction();
|
|
|
+ $hasTransaction = true;
|
|
|
+ }
|
|
|
+ $stm = $this->bd->prepare('ALTER TABLE `' . $this->prefix . 'entry` ADD COLUMN lastSeen INT(11) DEFAULT 0');
|
|
|
+ if ($stm && $stm->execute()) {
|
|
|
+ $stm = $this->bd->prepare('CREATE INDEX entry_lastSeen_index ON `' . $this->prefix . 'entry`(`lastSeen`);'); //"IF NOT EXISTS" does not exist in MySQL 5.7
|
|
|
+ if ($stm && $stm->execute()) {
|
|
|
if ($hasTransaction) {
|
|
|
- $this->bd->rollBack();
|
|
|
+ $this->bd->commit();
|
|
|
}
|
|
|
- } elseif (stripos($errorInfo[2], 'hash') !== false) { //v1.2
|
|
|
- $stm = $this->bd->prepare('ALTER TABLE `' . $this->prefix . 'entry` ADD COLUMN hash BINARY(16) NOT NULL');
|
|
|
- return $stm && $stm->execute();
|
|
|
+ return true;
|
|
|
}
|
|
|
- } catch (Exception $e) {
|
|
|
- Minz_Log::debug('FreshRSS_EntryDAO::autoAddColumn error: ' . $e->getMessage());
|
|
|
- if ($hasTransaction) {
|
|
|
- $this->bd->rollBack();
|
|
|
+ }
|
|
|
+ if ($hasTransaction) {
|
|
|
+ $this->bd->rollBack();
|
|
|
+ }
|
|
|
+ } elseif ($name === 'hash') { //v1.2
|
|
|
+ $stm = $this->bd->prepare('ALTER TABLE `' . $this->prefix . 'entry` ADD COLUMN hash BINARY(16)');
|
|
|
+ return $stm && $stm->execute();
|
|
|
+ }
|
|
|
+ } catch (Exception $e) {
|
|
|
+ Minz_Log::debug('FreshRSS_EntryDAO::autoAddColumn error: ' . $e->getMessage());
|
|
|
+ if ($hasTransaction) {
|
|
|
+ $this->bd->rollBack();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ protected function autoAddColumn($errorInfo) {
|
|
|
+ if (isset($errorInfo[0])) {
|
|
|
+ if ($errorInfo[0] == '42S22') { //ER_BAD_FIELD_ERROR
|
|
|
+ foreach (array('lastSeen', 'hash') as $column) {
|
|
|
+ if (stripos($errorInfo[2], $column) !== false) {
|
|
|
+ return $this->addColumn($column);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -54,7 +64,7 @@ class FreshRSS_EntryDAO extends Minz_ModelPdo implements FreshRSS_Searchable {
|
|
|
. ', link, date, lastSeen, hash, is_read, is_favorite, id_feed, tags) '
|
|
|
. 'VALUES(?, ?, ?, ?, '
|
|
|
. ($this->isCompressed() ? 'COMPRESS(?)' : '?')
|
|
|
- . ', ?, ?, ?, X?, ?, ?, ?, ?)';
|
|
|
+ . ', ?, ?, ?, ?, ?, ?, ?, ?)';
|
|
|
$this->addEntryPrepared = $this->bd->prepare($sql);
|
|
|
}
|
|
|
|
|
|
@@ -67,7 +77,7 @@ class FreshRSS_EntryDAO extends Minz_ModelPdo implements FreshRSS_Searchable {
|
|
|
substr($valuesTmp['link'], 0, 1023),
|
|
|
$valuesTmp['date'],
|
|
|
time(),
|
|
|
- $valuesTmp['hash'],
|
|
|
+ hex2bin($valuesTmp['hash']), // X'09AF' hexadecimal literals do not work with SQLite/PDO
|
|
|
$valuesTmp['is_read'] ? 1 : 0,
|
|
|
$valuesTmp['is_favorite'] ? 1 : 0,
|
|
|
$valuesTmp['id_feed'],
|
|
|
@@ -77,12 +87,12 @@ class FreshRSS_EntryDAO extends Minz_ModelPdo implements FreshRSS_Searchable {
|
|
|
if ($this->addEntryPrepared && $this->addEntryPrepared->execute($values)) {
|
|
|
return $this->bd->lastInsertId();
|
|
|
} else {
|
|
|
- $info = $this->addEntryPrepared == null ? array(2 => 'syntax error') : $this->addEntryPrepared->errorInfo();
|
|
|
+ $info = $this->addEntryPrepared == null ? array(0 => '', 1 => '', 2 => 'syntax error') : $this->addEntryPrepared->errorInfo();
|
|
|
if ($this->autoAddColumn($info)) {
|
|
|
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]
|
|
|
- . ' while adding entry in feed ' . $valuesTmp['id_feed'] . ' with title: ' . $valuesTmp['title']);
|
|
|
+ . ' while adding entry in feed ' . $valuesTmp['id_feed'] . ' with title: ' . $valuesTmp['title']. ' ' . $this->addEntryPrepared);
|
|
|
}
|
|
|
return false;
|
|
|
}
|
|
|
@@ -99,7 +109,7 @@ class FreshRSS_EntryDAO extends Minz_ModelPdo implements FreshRSS_Searchable {
|
|
|
$sql = 'UPDATE `' . $this->prefix . 'entry` '
|
|
|
. 'SET title=?, author=?, '
|
|
|
. ($this->isCompressed() ? 'content_bin=COMPRESS(?)' : 'content=?')
|
|
|
- . ', link=?, date=?, lastSeen=?, hash=X?, '
|
|
|
+ . ', link=?, date=?, lastSeen=?, hash=?, '
|
|
|
. ($valuesTmp['is_read'] === null ? '' : 'is_read=?, ')
|
|
|
. 'tags=? '
|
|
|
. 'WHERE id_feed=? AND guid=?';
|
|
|
@@ -113,7 +123,7 @@ class FreshRSS_EntryDAO extends Minz_ModelPdo implements FreshRSS_Searchable {
|
|
|
substr($valuesTmp['link'], 0, 1023),
|
|
|
$valuesTmp['date'],
|
|
|
time(),
|
|
|
- $valuesTmp['hash'],
|
|
|
+ hex2bin($valuesTmp['hash']),
|
|
|
);
|
|
|
if ($valuesTmp['is_read'] !== null) {
|
|
|
$values[] = $valuesTmp['is_read'] ? 1 : 0;
|
|
|
@@ -127,7 +137,7 @@ class FreshRSS_EntryDAO extends Minz_ModelPdo implements FreshRSS_Searchable {
|
|
|
if ($this->updateEntryPrepared && $this->updateEntryPrepared->execute($values)) {
|
|
|
return $this->bd->lastInsertId();
|
|
|
} else {
|
|
|
- $info = $this->updateEntryPrepared == null ? array(2 => 'syntax error') : $this->updateEntryPrepared->errorInfo();
|
|
|
+ $info = $this->updateEntryPrepared == null ? array(0 => '', 1 => '', 2 => 'syntax error') : $this->updateEntryPrepared->errorInfo();
|
|
|
if ($this->autoAddColumn($info)) {
|
|
|
return $this->updateEntry($valuesTmp);
|
|
|
}
|
|
|
@@ -597,8 +607,7 @@ class FreshRSS_EntryDAO extends Minz_ModelPdo implements FreshRSS_Searchable {
|
|
|
}
|
|
|
return $result;
|
|
|
} else {
|
|
|
-
|
|
|
- $info = $stm == null ? array(2 => 'syntax error') : $stm->errorInfo();
|
|
|
+ $info = $stm == null ? array(0 => '', 1 => '', 2 => 'syntax error') : $stm->errorInfo();
|
|
|
if ($this->autoAddColumn($info)) {
|
|
|
return $this->listHashForFeedGuids($id_feed, $guids);
|
|
|
}
|
|
|
@@ -619,7 +628,7 @@ class FreshRSS_EntryDAO extends Minz_ModelPdo implements FreshRSS_Searchable {
|
|
|
if ($stm && $stm->execute($values)) {
|
|
|
return $stm->rowCount();
|
|
|
} else {
|
|
|
- $info = $stm == null ? array(2 => 'syntax error') : $stm->errorInfo();
|
|
|
+ $info = $stm == null ? array(0 => '', 1 => '', 2 => 'syntax error') : $stm->errorInfo();
|
|
|
if ($this->autoAddColumn($info)) {
|
|
|
return $this->updateLastSeen($id_feed, $guids);
|
|
|
}
|