Loading core/lib/Drupal/Core/Database/Query/Update.php +47 −21 Original line number Diff line number Diff line Loading @@ -116,27 +116,9 @@ public function expression($field, $expression, ?array $arguments = NULL) { * actually didn't have to be updated because the values didn't change. */ public function execute() { // Expressions take priority over literal fields, so we process those first // and remove any literal fields that conflict. $fields = $this->fields; $update_values = []; foreach ($this->expressionFields as $field => $data) { 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]); } // Because we filter $fields the same way here and in __toString(), the // placeholders will all match up properly. $max_placeholder = 0; foreach ($fields as $value) { $update_values[':db_update_placeholder_' . ($max_placeholder++)] = $value; } [$args, $update_values] = $this->getQueryArguments(); $update_values += $args; if (count($this->condition)) { $this->condition->compile($this->connection, $this); Loading Loading @@ -178,8 +160,10 @@ public function __toString() { } $max_placeholder = 0; [$args] = $this->getQueryArguments(); $placeholders = array_keys($args); foreach ($fields as $field => $value) { $update_fields[] = $this->connection->escapeField($field) . '=:db_update_placeholder_' . ($max_placeholder++); $update_fields[] = $this->connection->escapeField($field) . '=' . $placeholders[$max_placeholder++]; } $query = $comments . 'UPDATE {' . $this->connection->escapeTable($this->table) . '} SET ' . implode(', ', $update_fields); Loading @@ -193,4 +177,46 @@ public function __toString() { return $query; } /** * {@inheritdoc} */ public function arguments() { [$args] = $this->getQueryArguments(); return $this->condition->arguments() + $args; } /** * Returns the query arguments with placeholders mapped to their values. * * @return array * An array containing arguments and update values. * Both arguments and update values are associative array where the keys * are the placeholder names and the values are the placeholder values. */ protected function getQueryArguments(): array { // Expressions take priority over literal fields, so we process those first // and remove any literal fields that conflict. $fields = $this->fields; $update_values = []; foreach ($this->expressionFields as $field => $data) { 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]); } // Because we filter $fields the same way here and in __toString(), the // placeholders will all match up properly. $max_placeholder = 0; $args = []; foreach ($fields as $value) { $args[':db_update_placeholder_' . ($max_placeholder++)] = $value; } return [$args, $update_values]; } } core/tests/Drupal/KernelTests/Core/Database/UpdateTest.php +26 −0 Original line number Diff line number Diff line Loading @@ -172,4 +172,30 @@ public function testUpdateValueInSerial(): void { ->execute(); } /** * Tests the Update::__toString() method. */ public function testToString(): void { // Prepare query for testing. $query = $this->connection->update('test') ->fields(['a' => 27, 'b' => 42]) ->condition('c', [1, 2], 'IN'); // Confirm placeholders are present. $query_string = (string) $query; $this->assertStringContainsString(':db_update_placeholder_0', $query_string); $this->assertStringContainsString(':db_update_placeholder_1', $query_string); $this->assertStringContainsString(':db_condition_placeholder_0', $query_string); $this->assertStringContainsString(':db_condition_placeholder_1', $query_string); // Test arguments. $expected = [ ':db_update_placeholder_0' => 27, ':db_update_placeholder_1' => 42, ':db_condition_placeholder_0' => 1, ':db_condition_placeholder_1' => 2, ]; $this->assertEquals($expected, $query->arguments()); } } Loading
core/lib/Drupal/Core/Database/Query/Update.php +47 −21 Original line number Diff line number Diff line Loading @@ -116,27 +116,9 @@ public function expression($field, $expression, ?array $arguments = NULL) { * actually didn't have to be updated because the values didn't change. */ public function execute() { // Expressions take priority over literal fields, so we process those first // and remove any literal fields that conflict. $fields = $this->fields; $update_values = []; foreach ($this->expressionFields as $field => $data) { 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]); } // Because we filter $fields the same way here and in __toString(), the // placeholders will all match up properly. $max_placeholder = 0; foreach ($fields as $value) { $update_values[':db_update_placeholder_' . ($max_placeholder++)] = $value; } [$args, $update_values] = $this->getQueryArguments(); $update_values += $args; if (count($this->condition)) { $this->condition->compile($this->connection, $this); Loading Loading @@ -178,8 +160,10 @@ public function __toString() { } $max_placeholder = 0; [$args] = $this->getQueryArguments(); $placeholders = array_keys($args); foreach ($fields as $field => $value) { $update_fields[] = $this->connection->escapeField($field) . '=:db_update_placeholder_' . ($max_placeholder++); $update_fields[] = $this->connection->escapeField($field) . '=' . $placeholders[$max_placeholder++]; } $query = $comments . 'UPDATE {' . $this->connection->escapeTable($this->table) . '} SET ' . implode(', ', $update_fields); Loading @@ -193,4 +177,46 @@ public function __toString() { return $query; } /** * {@inheritdoc} */ public function arguments() { [$args] = $this->getQueryArguments(); return $this->condition->arguments() + $args; } /** * Returns the query arguments with placeholders mapped to their values. * * @return array * An array containing arguments and update values. * Both arguments and update values are associative array where the keys * are the placeholder names and the values are the placeholder values. */ protected function getQueryArguments(): array { // Expressions take priority over literal fields, so we process those first // and remove any literal fields that conflict. $fields = $this->fields; $update_values = []; foreach ($this->expressionFields as $field => $data) { 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]); } // Because we filter $fields the same way here and in __toString(), the // placeholders will all match up properly. $max_placeholder = 0; $args = []; foreach ($fields as $value) { $args[':db_update_placeholder_' . ($max_placeholder++)] = $value; } return [$args, $update_values]; } }
core/tests/Drupal/KernelTests/Core/Database/UpdateTest.php +26 −0 Original line number Diff line number Diff line Loading @@ -172,4 +172,30 @@ public function testUpdateValueInSerial(): void { ->execute(); } /** * Tests the Update::__toString() method. */ public function testToString(): void { // Prepare query for testing. $query = $this->connection->update('test') ->fields(['a' => 27, 'b' => 42]) ->condition('c', [1, 2], 'IN'); // Confirm placeholders are present. $query_string = (string) $query; $this->assertStringContainsString(':db_update_placeholder_0', $query_string); $this->assertStringContainsString(':db_update_placeholder_1', $query_string); $this->assertStringContainsString(':db_condition_placeholder_0', $query_string); $this->assertStringContainsString(':db_condition_placeholder_1', $query_string); // Test arguments. $expected = [ ':db_update_placeholder_0' => 27, ':db_update_placeholder_1' => 42, ':db_condition_placeholder_0' => 1, ':db_condition_placeholder_1' => 2, ]; $this->assertEquals($expected, $query->arguments()); } }