Index: webform.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/webform/webform.module,v
retrieving revision 1.196.2.21
diff -u -r1.196.2.21 webform.module
--- webform.module	10 Apr 2010 02:20:38 -0000	1.196.2.21
+++ webform.module	10 Apr 2010 06:07:18 -0000
@@ -857,7 +857,6 @@
   // Insert the components into the database. Used with clone.module.
   if (isset($node->webform['components']) && !empty($node->webform['components'])) {
     foreach ($node->webform['components'] as $cid => $component) {
-      $component['nid'] = $node->nid;
       webform_component_insert($component);
     }
   }
@@ -876,11 +875,51 @@
     return;
   }
 
-  // Update the webform by deleting existing data and replacing with the new.
-  db_query('DELETE FROM {webform} WHERE nid = %d', $node->nid);
-  db_query('DELETE FROM {webform_component} WHERE nid = %d', $node->nid);
-  db_query('DELETE FROM {webform_roles} WHERE nid = %d', $node->nid);
-  webform_node_insert($node);
+  // Check if there is an existing entry at all for this node.
+  $exists = db_result(db_query('SELECT nid FROM {webform} WHERE nid = %d', $node->nid));
+
+  // If a webform row doesn't even exist, we can assume it needs to be inserted.
+  if (!$exists) {
+    webform_node_insert($node);
+    return;
+  }
+
+  // Update the webform entry.
+  db_query("UPDATE {webform} SET confirmation = '%s', confirmation_format = %d, redirect_url = '%s', teaser = %d, allow_draft = %d, submit_notice = %d, submit_text = '%s', submit_limit = %d, submit_interval = %d where nid = %d", $node->webform['confirmation'], $node->webform['confirmation_format'], $node->webform['redirect_url'], $node->webform['teaser'], $node->webform['allow_draft'], $node->webform['submit_notice'], $node->webform['submit_text'], $node->webform['submit_limit'], $node->webform['submit_interval'], $node->nid);
+
+  // Compare the webform components and don't do anything if it's not needed.
+  $original = node_load($node->nid);
+
+  if ($original->webform['components'] != $node->webform['components']) {
+    module_load_include('inc', 'webform', 'includes/webform.components');
+
+    $original_cids = array_keys($original->webform['components']);
+    $current_cids = array_keys($node->webform['components']);
+
+    $all_cids = $original_cids + $current_cids;
+    $deleted_cids = array_diff($original_cids, $current_cids);
+    $inserted_cids = array_diff($current_cids, $original_cids);
+
+    foreach ($all_cids as $cid) {
+      if (in_array($cid, $inserted_cids)) {
+        webform_component_insert($node->webform['components'][$cid]);
+      }
+      elseif (in_array($cid, $deleted_cids)) {
+        webform_component_delete($node, $original->webform['components'][$cid]);
+      }
+      elseif ($node->webform['components'][$cid] != $original->webform['components'][$cid]) {
+        webform_component_update($node->webform['components'][$cid]);
+      }
+    }
+  }
+
+  // Just delete and re-insert roles if they've changed.
+  if ($original->webform['roles'] != $node->webform['roles']) {
+    db_query('DELETE FROM {webform_roles} WHERE nid = %d', $node->nid);
+    foreach (array_filter($node->webform['roles']) as $rid) {
+      db_query('INSERT INTO {webform_roles} (nid, rid) VALUES (%d, %d)', $node->nid, $rid);
+    }
+  }
 }
 
 /**
