From 1b2f1cc2720682b253891a03c05e225cc7ca8882 Mon Sep 17 00:00:00 2001
From: Robin McCorkell <robin@mccorkell.me.uk>
Date: Fri, 11 Mar 2016 17:22:29 +0000
Subject: [PATCH] Prevent certain DBs throwing exceptions on same-value updates

A PreconditionNotMetException must only be thrown if explicit
preconditions are specified for setValues(), not if the value is merely
the same as was already in the DB.
---
 lib/private/db/connection.php |  2 +-
 tests/lib/db/connection.php   | 30 ++++++++++++++++++++++++------
 2 files changed, 25 insertions(+), 7 deletions(-)

diff --git a/lib/private/db/connection.php b/lib/private/db/connection.php
index 584904e6370..7904fab0726 100644
--- a/lib/private/db/connection.php
+++ b/lib/private/db/connection.php
@@ -293,7 +293,7 @@ class Connection extends \Doctrine\DBAL\Connection implements IDBConnection {
 			$updateQb->where($where);
 			$affected = $updateQb->execute();
 
-			if ($affected === 0) {
+			if ($affected === 0 && !empty($updatePreconditionValues)) {
 				throw new PreconditionNotMetException();
 			}
 
diff --git a/tests/lib/db/connection.php b/tests/lib/db/connection.php
index b10b1a322a9..62d0a77ca1f 100644
--- a/tests/lib/db/connection.php
+++ b/tests/lib/db/connection.php
@@ -47,6 +47,11 @@ class Connection extends \Test\TestCase {
 		$this->connection = \OC::$server->getDatabaseConnection();
 	}
 
+	public function tearDown() {
+		parent::tearDown();
+		$this->connection->dropTable('table');
+	}
+
 	/**
 	 * @param string $table
 	 */
@@ -86,6 +91,7 @@ class Connection extends \Test\TestCase {
 	 * @depends testTableExists
 	 */
 	public function testDropTable() {
+		$this->makeTestTable();
 		$this->assertTableExist('table');
 		$this->connection->dropTable('table');
 		$this->assertTableNotExist('table');
@@ -111,8 +117,6 @@ class Connection extends \Test\TestCase {
 		]);
 
 		$this->assertEquals('foo', $this->getTextValueByIntergerField(1));
-
-		$this->connection->dropTable('table');
 	}
 
 	public function testSetValuesOverWrite() {
@@ -131,8 +135,6 @@ class Connection extends \Test\TestCase {
 		]);
 
 		$this->assertEquals('bar', $this->getTextValueByIntergerField(1));
-
-		$this->connection->dropTable('table');
 	}
 
 	public function testSetValuesOverWritePrecondition() {
@@ -154,8 +156,6 @@ class Connection extends \Test\TestCase {
 		]);
 
 		$this->assertEquals('bar', $this->getTextValueByIntergerField(1));
-
-		$this->connection->dropTable('table');
 	}
 
 	/**
@@ -179,4 +179,22 @@ class Connection extends \Test\TestCase {
 			'booleanfield' => false
 		]);
 	}
+
+	public function testSetValuesSameNoError() {
+		$this->makeTestTable();
+		$this->connection->setValues('table', [
+			'integerfield' => 1
+		], [
+			'textfield' => 'foo',
+			'clobfield' => 'not_null'
+		]);
+
+		// this will result in 'no affected rows' on certain optimizing DBs
+		// ensure the PreConditionNotMetException isn't thrown
+		$this->connection->setValues('table', [
+			'integerfield' => 1
+		], [
+			'textfield' => 'foo'
+		]);
+	}
 }
-- 
GitLab