diff --git a/core/lib/Drupal/Core/Database/Query/Merge.php b/core/lib/Drupal/Core/Database/Query/Merge.php index ee0406a..0bff74c 100644 --- a/core/lib/Drupal/Core/Database/Query/Merge.php +++ b/core/lib/Drupal/Core/Database/Query/Merge.php @@ -403,42 +403,57 @@ class Merge extends Query implements ConditionInterface { } public function execute() { - if (!count($this->condition)) { - throw new InvalidMergeQueryException(t('Invalid merge query: no conditions')); - } - $select = $this->connection->select($this->conditionTable) - ->condition($this->condition); - $select->addExpression('1'); - if (!$select->execute()->fetchField()) { - try { - $insert = $this->connection->insert($this->table)->fields($this->insertFields); - if ($this->defaultFields) { - $insert->useDefaults($this->defaultFields); + // Default options for merge queries. + $this->queryOptions += array( + 'throw_exception' => TRUE, + ); + + try { + if (!count($this->condition)) { + throw new InvalidMergeQueryException(t('Invalid merge query: no conditions')); + } + $select = $this->connection->select($this->conditionTable) + ->condition($this->condition); + $select->addExpression('1'); + if (!$select->execute()->fetchField()) { + try { + $insert = $this->connection->insert($this->table)->fields($this->insertFields); + if ($this->defaultFields) { + $insert->useDefaults($this->defaultFields); + } + $insert->execute(); + return self::STATUS_INSERT; + } + catch (IntegrityConstraintViolationException $e) { + // The insert query failed, maybe it's because a racing insert query + // beat us in inserting the same row. Retry the select query, if it + // returns a row, ignore the error and continue with the update + // query below. + if (!$select->execute()->fetchField()) { + throw $e; + } } - $insert->execute(); - return self::STATUS_INSERT; } - catch (IntegrityConstraintViolationException $e) { - // The insert query failed, maybe it's because a racing insert query - // beat us in inserting the same row. Retry the select query, if it - // returns a row, ignore the error and continue with the update - // query below. - if (!$select->execute()->fetchField()) { - throw $e; + if ($this->needsUpdate) { + $update = $this->connection->update($this->table) + ->fields($this->updateFields) + ->condition($this->condition); + if ($this->expressionFields) { + foreach ($this->expressionFields as $field => $data) { + $update->expression($field, $data['expression'], $data['arguments']); + } } + $update->execute(); + return self::STATUS_UPDATE; } } - if ($this->needsUpdate) { - $update = $this->connection->update($this->table) - ->fields($this->updateFields) - ->condition($this->condition); - if ($this->expressionFields) { - foreach ($this->expressionFields as $field => $data) { - $update->expression($field, $data['expression'], $data['arguments']); - } + catch (\Exception $e) { + if ($this->queryOptions['throw_exception']) { + throw $e; + } + else { + return NULL; } - $update->execute(); - return self::STATUS_UPDATE; } } } diff --git a/core/lib/Drupal/Core/Database/Query/Select.php b/core/lib/Drupal/Core/Database/Query/Select.php index 1bfe9a0..e5eeaf2 100644 --- a/core/lib/Drupal/Core/Database/Query/Select.php +++ b/core/lib/Drupal/Core/Database/Query/Select.php @@ -589,7 +589,7 @@ class Select extends Query implements SelectInterface { public function countQuery() { $count = $this->prepareCountQuery(); - $query = $this->connection->select($count); + $query = $this->connection->select($count, NULL, $this->queryOptions); $query->addExpression('COUNT(*)'); return $query; diff --git a/core/modules/system/lib/Drupal/system/Tests/Database/MergeTest.php b/core/modules/system/lib/Drupal/system/Tests/Database/MergeTest.php index d5d6909..78ef33d 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Database/MergeTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Database/MergeTest.php @@ -208,7 +208,25 @@ function testMergeUpdateWithoutUpdate() { */ function testInvalidMerge() { try { - // This query should die because there is no key field specified. + // This query will fail because there is no key field specified. + // Normally it would throw an exception but we are supressing it with + // the throw_exception option. + $options['throw_exception'] = FALSE; + db_merge('test_people', $options) + ->fields(array( + 'age' => 31, + 'name' => 'Tiffany', + )) + ->execute(); + $this->pass('$options[\'throw_exception\'] is FALSE, no InvalidMergeQueryException thrown.'); + } + catch (InvalidMergeQueryException $e) { + $this->fail('$options[\'throw_exception\'] is FALSE, but InvalidMergeQueryException thrown for invalid query.'); + return; + } + + try { + // This query will fail because there is no key field specified. db_merge('test_people') ->fields(array( 'age' => 31, diff --git a/core/modules/system/lib/Drupal/system/Tests/Database/SelectTest.php b/core/modules/system/lib/Drupal/system/Tests/Database/SelectTest.php index 85787b8..e840ed0 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Database/SelectTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Database/SelectTest.php @@ -376,4 +376,40 @@ function testSelectDuplicateAlias() { $alias2 = $query->addField('t', 'age', 'the_alias'); $this->assertNotIdentical($alias1, $alias2, 'Duplicate aliases are renamed.'); } + + /** + * Tests that an invalid merge query throws an exception. + */ + function testInvalidSelectCount() { + try { + // This query will fail because the table does not exist. + // Normally it would throw an exception but we are supressing + // it with the throw_exception option. + $options['throw_exception'] = FALSE; + db_select('some_table_that_doesnt_exist', 't', $options) + ->fields('t') + ->countQuery() + ->execute(); + + $this->pass('$options[\'throw_exception\'] is FALSE, no Exception thrown.'); + } + catch (\Exception $e) { + $this->fail('$options[\'throw_exception\'] is FALSE, but Exception thrown for invalid query.'); + return; + } + + try { + // This query will fail because the table does not exist. + db_select('some_table_that_doesnt_exist', 't') + ->fields('t') + ->countQuery() + ->execute(); + } + catch (\Exception $e) { + $this->pass('Exception thrown for invalid query.'); + return; + } + $this->fail('No Exception thrown.'); + } + }