Index: includes/database/database.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/database/database.inc,v retrieving revision 1.33 diff -u -p -r1.33 database.inc --- includes/database/database.inc 8 Dec 2008 21:41:53 -0000 1.33 +++ includes/database/database.inc 10 Dec 2008 04:28:58 -0000 @@ -1121,6 +1121,14 @@ abstract class Database { class TransactionsNotSupportedException extends PDOException { } /** + * Exception thrown for merge queries that do not make semantic sense. + * + * There are many ways that a merge query could be malformed. They should all + * throw this exception and set an appropriately descriptive message. + */ +class InvalidMergeQueryException extends Exception {} + +/** * A wrapper class for creating and managing database transactions. * * Not all databases or database configurations support transactions. For Index: includes/database/query.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/database/query.inc,v retrieving revision 1.9 diff -u -p -r1.9 query.inc --- includes/database/query.inc 8 Dec 2008 21:41:53 -0000 1.9 +++ includes/database/query.inc 10 Dec 2008 04:28:58 -0000 @@ -635,6 +635,11 @@ class MergeQuery extends Query { public function execute() { + // A merge query without any key field is invalid. + if (count($this->keyFields) == 0) { + throw new InvalidMergeQueryException("You need to specify key fields before executing a merge query"); + } + // In the degenerate case of this query type, we have to run multiple // queries as there is no universal single-query mechanism that will work. // Our degenerate case is not designed for performance efficiency but Index: includes/database/mysql/query.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/database/mysql/query.inc,v retrieving revision 1.6 diff -u -p -r1.6 query.inc --- includes/database/mysql/query.inc 13 Nov 2008 21:08:15 -0000 1.6 +++ includes/database/mysql/query.inc 10 Dec 2008 04:28:58 -0000 @@ -80,6 +80,12 @@ class InsertQuery_mysql extends InsertQu class MergeQuery_mysql extends MergeQuery { public function execute() { + + // A merge query without any key field is invalid. + if (count($this->keyFields) == 0) { + throw new InvalidMergeQueryException("You need to specify key fields before executing a merge query"); + } + // Set defaults. if ($this->updateFields) { $update_fields = $this->updateFields; Index: modules/aggregator/aggregator.module =================================================================== RCS file: /cvs/drupal/drupal/modules/aggregator/aggregator.module,v retrieving revision 1.401 diff -u -p -r1.401 aggregator.module --- modules/aggregator/aggregator.module 16 Nov 2008 04:38:15 -0000 1.401 +++ modules/aggregator/aggregator.module 10 Dec 2008 04:28:59 -0000 @@ -936,9 +936,9 @@ function aggregator_save_item($edit) { $result = db_query('SELECT cid FROM {aggregator_category_feed} WHERE fid = :fid', array(':fid' => $edit['fid'])); foreach ($result as $category) { db_merge('aggregator_category_item') + ->key(array('iid' => $edit['iid'])) ->fields(array( 'cid' => $category->cid, - 'iid' => $edit['iid'], )) ->execute(); } Index: modules/simpletest/tests/database_test.test =================================================================== RCS file: /cvs/drupal/drupal/modules/simpletest/tests/database_test.test,v retrieving revision 1.25 diff -u -p -r1.25 database_test.test --- modules/simpletest/tests/database_test.test 8 Dec 2008 22:02:45 -0000 1.25 +++ modules/simpletest/tests/database_test.test 10 Dec 2008 04:28:59 -0000 @@ -957,6 +957,26 @@ class DatabaseMergeTestCase extends Data $this->assertEqual($person->age, $age_before + 4, t('Age updated correctly.')); $this->assertEqual($person->job, 'Speaker', t('Job set correctly.')); } + + /** + * Test that an invalid merge query throws an exception like it is supposed to. + */ + function testInvalidMerge() { + try { + // This query should die because there is no key field specified. + db_merge('test_people') + ->fields(array( + 'age' => 31, + 'name' => 'Tiffany', + )) + ->execute(); + } + catch (InvalidMergeQueryException $e) { + $this->pass(t('InvalidMergeQueryException thrown for invalid query.')); + return; + } + $this->fail(t('No InvalidMergeQueryException thrown')); + } } /** Index: modules/statistics/statistics.module =================================================================== RCS file: /cvs/drupal/drupal/modules/statistics/statistics.module,v retrieving revision 1.288 diff -u -p -r1.288 statistics.module --- modules/statistics/statistics.module 9 Dec 2008 11:30:25 -0000 1.288 +++ modules/statistics/statistics.module 10 Dec 2008 04:28:59 -0000 @@ -51,14 +51,13 @@ function statistics_exit() { // We are counting content views. if ((arg(0) == 'node') && is_numeric(arg(1)) && arg(2) == '') { // A node has been viewed, so update the node's counters. - $fields = array( - 'daycount' => 1, - 'totalcount' => 1, - 'nid' => arg(1), - 'timestamp' => REQUEST_TIME, - ); db_merge('node_counter') - ->fields($fields) + ->key(array('nid' => arg(1))) + ->fields(array( + 'daycount' => 1, + 'totalcount' => 1, + 'timestamp' => REQUEST_TIME, + )) ->expression('daycount', 'daycount + 1') ->expression('totalcount', 'totalcount + 1') ->execute();