#332002: MergeQuery should refuse to execute if there are no key fields.

From: Damien Tournoud <damien@tournoud.net>

Those queries make no sense because they essentially mean "if any row exist in the table, replace with the fields I indicate".
---

 includes/database/mysql/query.inc    |    6 ++++++
 includes/database/query.inc          |    5 +++++
 modules/aggregator/aggregator.module |    4 ++--
 modules/statistics/statistics.module |   13 ++++++-------
 4 files changed, 19 insertions(+), 9 deletions(-)


diff --git includes/database/mysql/query.inc includes/database/mysql/query.inc
index b23eefc..f46bec1 100644
--- includes/database/mysql/query.inc
+++ includes/database/mysql/query.inc
@@ -76,6 +76,12 @@ class InsertQuery_mysql extends InsertQuery {
 class MergeQuery_mysql extends MergeQuery {
 
   public function execute() {
+
+    // A merge query without any key field is invalid.
+    if (count($this->keyFields) == 0) {
+      throw new PDOException("You need to specify key fields before executing a merge query");
+    }
+
     // Set defaults.
     if ($this->updateFields) {
       $update_fields = $this->updateFields;
diff --git includes/database/query.inc includes/database/query.inc
index 5ecc8ce..6531685 100644
--- includes/database/query.inc
+++ includes/database/query.inc
@@ -629,6 +629,11 @@ class MergeQuery extends Query {
 
   public function execute() {
 
+    // A merge query without any key field is invalid.
+    if (count($this->keyFields) == 0) {
+      throw new PDOException("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
diff --git modules/aggregator/aggregator.module modules/aggregator/aggregator.module
index 81e2b45..3f6d602 100644
--- modules/aggregator/aggregator.module
+++ modules/aggregator/aggregator.module
@@ -477,8 +477,8 @@ function aggregator_save_feed($edit) {
       foreach ($edit['category'] as $cid => $value) {
         if ($value) {
           db_merge('aggregator_category_feed')
+            ->key(array('fid', $edit['fid']))
             ->fields(array(
-              'fid' => $edit['fid'],
               'cid' => $cid,
             ))
             ->execute();
@@ -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();
     }
diff --git modules/statistics/statistics.module modules/statistics/statistics.module
index 9d4632f..4b28bd2 100644
--- modules/statistics/statistics.module
+++ modules/statistics/statistics.module
@@ -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();
