diff --git a/core/lib/Drupal/Core/Database/Query/Update.php b/core/lib/Drupal/Core/Database/Query/Update.php index 5ffdb33dba244ff239eb785379dbc7e1b15d3f51..326ec298b60f53f742dfb5452f0b83a9ed9962b7 100644 --- a/core/lib/Drupal/Core/Database/Query/Update.php +++ b/core/lib/Drupal/Core/Database/Query/Update.php @@ -212,6 +212,10 @@ public function execute() { if (!empty($data['arguments'])) { $update_values += $data['arguments']; } + if ($data['expression'] instanceof SelectInterface) { + $data['expression']->compile($this->connection, $this); + $update_values += $data['expression']->arguments(); + } unset($fields[$field]); } @@ -245,6 +249,11 @@ public function __toString() { $fields = $this->fields; $update_fields = array(); foreach ($this->expressionFields as $field => $data) { + if ($data['expression'] instanceof SelectInterface) { + // Compile and cast expression subquery to a string. + $data['expression']->compile($this->connection, $this); + $data['expression'] = ' (' . $data['expression'] . ')'; + } $update_fields[] = $field . '=' . $data['expression']; unset($fields[$field]); } diff --git a/core/modules/system/lib/Drupal/system/Tests/Database/UpdateComplexTest.php b/core/modules/system/lib/Drupal/system/Tests/Database/UpdateComplexTest.php index 477836363bf56372dacb17c4d300b75c1d2071d0..99bd178d7ad8bc6de3ed460bd3be3c31bb40921b 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Database/UpdateComplexTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Database/UpdateComplexTest.php @@ -132,4 +132,28 @@ function testUpdateOnlyExpression() { $after_age = db_query('SELECT age FROM {test} WHERE name = :name', array(':name' => 'Ringo'))->fetchField(); $this->assertEqual($before_age + 4, $after_age, 'Age updated correctly'); } + + /** + * Test UPDATE with a subselect value. + */ + function testSubSelectUpdate() { + $subselect = db_select('test_task', 't'); + $subselect->addExpression('MAX(priority) + :increment', 'max_priority', array(':increment' => 30)); + // Clone this to make sure we are running a different query when + // asserting. + $select = clone $subselect; + $query = db_update('test') + ->expression('age', $subselect) + ->condition('name', 'Ringo'); + // Save the query for a __toString test later. + $string_test = $query; + $query->execute(); + $after_age = db_query('SELECT age FROM {test} WHERE name = :name', array(':name' => 'Ringo'))->fetchField(); + $expected_age = $select->execute()->fetchField(); + $this->assertEqual($after_age, $expected_age); + // Replace whitespace with a single space. + $query_string = preg_replace('/\s+/', ' ', $string_test); + $this->assertIdentical('UPDATE {test} SET age= (SELECT MAX(priority) + :increment AS max_priority FROM {test_task} t) WHERE (name = :db_condition_placeholder_0)', trim($query_string)); + } + }