From bfaa7b4fd0c0b16e38ba3475d0be24b1d5f9a5d1 Mon Sep 17 00:00:00 2001
From: David Rothstein <drothstein@gmail.com>
Date: Wed, 27 Feb 2013 18:13:58 -0500
Subject: [PATCH] Issue #1266572 by znerol, joshf: Fixed Workaround in
 UpdateQuery_sqlite() for affected rows count causes certain updates to be
 suppressed.

---
 CHANGELOG.txt                               |  2 ++
 includes/database/sqlite/query.inc          | 27 +++------------------
 modules/simpletest/tests/database_test.test | 14 +++++++++++
 3 files changed, 19 insertions(+), 24 deletions(-)

diff --git a/CHANGELOG.txt b/CHANGELOG.txt
index affd50f2d9de..58222671e622 100644
--- a/CHANGELOG.txt
+++ b/CHANGELOG.txt
@@ -1,6 +1,8 @@
 
 Drupal 7.21, xxxx-xx-xx (development version)
 -----------------------
+- Fixed a bug with update queries in the SQLite database driver that prevented
+  Drupal from being installed with SQLite on PHP 5.4.
 - Fixed enforced dependencies errors updating to recent versions of Drupal 7 on
   certain non-MySQL databases.
 - Refactored the Field module's caching behavior to obtain large improvements
diff --git a/includes/database/sqlite/query.inc b/includes/database/sqlite/query.inc
index 74ff9ba200ec..1bf609db10f5 100644
--- a/includes/database/sqlite/query.inc
+++ b/includes/database/sqlite/query.inc
@@ -57,39 +57,18 @@ public function __toString() {
  * we don't select those rows.
  *
  * A query like this one:
- *   UPDATE test SET name = 'newname' WHERE tid = 1
+ *   UPDATE test SET col1 = 'newcol1', col2 = 'newcol2' WHERE tid = 1
  * will become:
- *   UPDATE test SET name = 'newname' WHERE tid = 1 AND name <> 'newname'
+ *   UPDATE test SET col1 = 'newcol1', col2 = 'newcol2' WHERE tid = 1 AND (col1 <> 'newcol1' OR col2 <> 'newcol2')
  */
 class UpdateQuery_sqlite extends UpdateQuery {
-  /**
-   * Helper function that removes the fields that are already in a condition.
-   *
-   * @param $fields
-   *   The fields.
-   * @param QueryConditionInterface $condition
-   *   A database condition.
-   */
-  protected function removeFieldsInCondition(&$fields, QueryConditionInterface $condition) {
-    foreach ($condition->conditions() as $child_condition) {
-      if ($child_condition['field'] instanceof QueryConditionInterface) {
-        $this->removeFieldsInCondition($fields, $child_condition['field']);
-      }
-      else {
-        unset($fields[$child_condition['field']]);
-      }
-    }
-  }
-
   public function execute() {
     if (!empty($this->queryOptions['sqlite_return_matched_rows'])) {
       return parent::execute();
     }
 
-    // Get the fields used in the update query, and remove those that are already
-    // in the condition.
+    // Get the fields used in the update query.
     $fields = $this->expressionFields + $this->fields;
-    $this->removeFieldsInCondition($fields, $this->condition);
 
     // Add the inverse of the fields to the condition.
     $condition = new DatabaseCondition('OR');
diff --git a/modules/simpletest/tests/database_test.test b/modules/simpletest/tests/database_test.test
index e7ce14f7acbe..b58578e993f7 100644
--- a/modules/simpletest/tests/database_test.test
+++ b/modules/simpletest/tests/database_test.test
@@ -848,6 +848,20 @@ class DatabaseUpdateTestCase extends DatabaseTestCase {
       ->execute();
     $this->assertIdentical($num_rows, 3, 'Number of affected rows are returned.');
   }
+
+  /**
+   * Confirm that we can update the primary key of a record successfully.
+   */
+  function testPrimaryKeyUpdate() {
+    $num_updated = db_update('test')
+      ->fields(array('id' => 42, 'name' => 'John'))
+      ->condition('id', 1)
+      ->execute();
+    $this->assertIdentical($num_updated, 1, 'Updated 1 record.');
+
+    $saved_name= db_query('SELECT name FROM {test} WHERE id = :id', array(':id' => 42))->fetchField();
+    $this->assertIdentical($saved_name, 'John', 'Updated primary key successfully.');
+  }
 }
 
 /**
-- 
GitLab