Index: advpoll.install
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/advpoll/advpoll.install,v
retrieving revision 1.5.2.16
diff -u -p -r1.5.2.16 advpoll.install
--- advpoll.install	4 Oct 2007 07:02:52 -0000	1.5.2.16
+++ advpoll.install	24 Nov 2007 23:35:21 -0000
@@ -32,12 +32,13 @@ function advpoll_install() {
       ) /*!40100 DEFAULT CHARACTER SET utf8 */");
 
       db_query("CREATE TABLE {advpoll_choices} (
+        cid unsigned int NOT NULL auto_increment,
         nid int(10) NOT NULL,
         label text NOT NULL,
-        vote_offset int(2) unsigned default NULL,
+        vote_offset int unsigned NOT NULL,
         writein tinyint NOT NULL default '0',
-        PRIMARY KEY (nid, vote_offset),
-        KEY vote_offset (vote_offset)
+        PRIMARY KEY (cid),
+        KEY nid_vote_offset (nid, vote_offset)
       ) /*!40100 DEFAULT CHARACTER SET utf8 */");
       break;
 
@@ -66,13 +67,14 @@ function advpoll_install() {
       )");
 
       db_query("CREATE TABLE {advpoll_choices} (
+        cid serial,
         nid integer NOT NULL,
         label text NOT NULL,
-        vote_offset smallint default NULL,
+        vote_offset smallint NOT NULL,
         writein smallint NOT NULL default '0',
-        PRIMARY KEY (nid, vote_offset)
+        PRIMARY KEY (cid)
       )");
-      db_query("CREATE INDEX {advpoll_choices}_vote_offset_idx ON {advpoll_choices} (vote_offset)");
+      db_query('CREATE INDEX {advpoll_choices} {advpoll_choices}_nid_vote_offset_idx ON {advpoll_choices} (nid, vote_offset)');
       break;
   }
 }
@@ -266,3 +268,35 @@ function advpoll_update_6() {
   }
   return $ret;
 }
+
+/**
+ * Refactor the advpoll_choices database table.
+ * 
+ * Change vote_offset to be NOT NULL, remove the extra key on vote_offset, and add an auto_increment id to each choice.
+ */
+function advpoll_update_7() {
+  $ret = array();
+  switch ($GLOBALS['db_type']) {
+    case 'mysql':
+    case 'mysqli':
+      $ret[] = update_sql('ALTER TABLE {advpoll_choices} CHANGE vote_offset vote_offset int NOT NULL');
+      $ret[] = update_sql('ALTER TABLE {advpoll_choices} DROP INDEX vote_offset');
+      $ret[] = update_sql('ALTER TABLE {advpoll_choices} DROP PRIMARY KEY');
+      $ret[] = update_sql('ALTER TABLE {advpoll_choices} ADD cid INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY FIRST');
+      break;
+    case 'pgsql':
+      db_change_column($ret, 'advpoll_choices', 'vote_offset', 'vote_offset', 'smallint', array('not null' => TRUE));
+      $ret[] = update_sql('ALTER TABLE {advpoll_choices} DROP CONSTRAINT {advpoll_choices}_vote_offset_idx');
+      $ret[] = update_sql('ALTER TABLE {advpoll_choices} DROP CONSTRAINT {advpoll_choices}_pkey');
+      db_add_column($ret, 'advpoll_choices', 'cid', 'serial', array('not null' => TRUE));
+      $ret[] = update_sql('ALTER TABLE {advpoll_choices} ADD PRIMARY KEY (cid)');
+      break;
+  }
+  // Votes should reference the cid rather than the vote_offset of each choice.
+  $result = db_query('SELECT nid, cid, vote_offset FROM {advpoll_choices}');
+  while ($choice = db_fetch_object($result)) {
+    db_query('UPDATE {votingapi_vote} SET tag = %d WHERE content_id = %d AND tag = %d', $choice->cid, $choice->nid, $choice->vote_offset);
+  }
+  return $ret;
+}
+
Index: advpoll.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/advpoll/advpoll.module,v
retrieving revision 1.21.2.74
diff -u -p -r1.21.2.74 advpoll.module
--- advpoll.module	10 Oct 2007 09:37:38 -0000	1.21.2.74
+++ advpoll.module	24 Nov 2007 23:35:21 -0000
@@ -577,9 +577,9 @@ function advpoll_form_alter($form_id, &$
 function advpoll_load($node) {
   global $user;
   $poll = db_fetch_object(db_query('SELECT * FROM {advpoll} WHERE nid = %d', $node->nid));
-  $result = db_query('SELECT vote_offset, label, writein FROM {advpoll_choices} WHERE nid = %d ORDER BY vote_offset', $node->nid);
+  $result = db_query('SELECT cid, vote_offset, label, writein FROM {advpoll_choices} WHERE nid = %d ORDER BY vote_offset', $node->nid);
   while ($choice = db_fetch_array($result)) {
-    $poll->choice[$choice['vote_offset']] = $choice;
+    $poll->choice[$choice['cid']] = $choice;
   }
   $poll->choices = count($poll->choice);
 
@@ -1078,10 +1078,16 @@ function _advpoll_is_active($node, $retu
 
 function _advpoll_insert_choices($nid) {
   $node = node_load($nid);
-  db_query('DELETE FROM {advpoll_choices} WHERE nid = %d', $nid);
+  $vote_offset = 0;
   foreach ($_POST['choice'] as $index => $choice) {
     if ($choice['label'] != '') {
-      db_query("INSERT INTO {advpoll_choices} (nid, label, vote_offset, writein) VALUES (%d, '%s', %d, %d)", $nid, $choice['label'], $index, isset($node->choice[$index]) ? $node->choice[$index]['writein'] : 0);
+      if (!isset($node->choice[$index])) {
+        db_query("INSERT INTO {advpoll_choices} (nid, label, vote_offset, writein) VALUES (%d, '%s', %d, 0)", $nid, $choice['label'], $vote_offset);
+      }
+      else {
+        db_query("UPDATE {advpoll_choices} SET label = '%s', vote_offset = %d WHERE cid = %d", $choice['label'], $vote_offset, $index);
+      }
+      $vote_offset++;
     }
   }
 }
@@ -1195,9 +1201,9 @@ function _advpoll_vote_response($node, $
     unset($node->choice);
     // Get all choices from database. This is necessary to get information about
     // newly submitted write-in choices.
-    $result = db_query('SELECT vote_offset, label, writein FROM {advpoll_choices} WHERE nid = %d ORDER BY vote_offset', $node->nid);
+    $result = db_query('SELECT cid, vote_offset, label, writein FROM {advpoll_choices} WHERE nid = %d ORDER BY vote_offset', $node->nid);
     while ($choice = db_fetch_array($result)) {
-      $node->choice[$choice['vote_offset']] = $choice;
+      $node->choice[$choice['cid']] = $choice;
     }
     // Update the number of choices.
     $node->choices = count($poll->choice);
@@ -1389,37 +1395,40 @@ function _advpoll_writeins_voting_form_s
   // A write-in vote is being made.
   if ($form_values['writein_choice']) {
     // Check if someone has previously voted for this choice.
-    $result = db_query("SELECT vote_offset FROM {advpoll_choices} WHERE nid = %d AND LOWER(label) = LOWER('%s')", $node->nid, $form_values['writein_choice']);
+    $result = db_query("SELECT cid FROM {advpoll_choices} WHERE nid = %d AND LOWER(label) = LOWER('%s')", $node->nid, $form_values['writein_choice']);
     // If there's more than one match, redo the query, being more exact.
     if (db_num_rows($result) > 1) {
-      $result = db_query("SELECT vote_offset FROM {advpoll_choices} WHERE nid = %d AND label = '%s'", $node->nid, $form_values['writein_choice']);      
+      $result = db_query("SELECT cid FROM {advpoll_choices} WHERE nid = %d AND label = '%s'", $node->nid, $form_values['writein_choice']);      
     }
     // If there is at least one match, add a vote for the first one returned. It
     // should be rare to find more than one choice for any one node with a given
     // label.
     if (db_num_rows($result)) {
       $obj = db_fetch_object($result);
-      $existing_vote_offset = $obj->vote_offset;
+      $existing_choice = $obj->cid;
       // Set a vote
       $vote = new stdClass();
       $vote->value = $vote_value;
-      $vote->tag = $existing_vote_offset;
+      $vote->tag = $existing_choice;
       $vote->value_type = 'option';
       $votes[] = $vote;
     }
     // This write-in choice has not been previously voted for.
     else {
-      // Get last vote offset for this node.
+      // Get highest vote offset for this node.
       $highest_offset = db_result(db_query("SELECT MAX(vote_offset) FROM {advpoll_choices} WHERE nid = %d", $node->nid));
       $next_offset = $highest_offset ? $highest_offset + 1 : 1;
 
-      // Insert new choice into node.
+      // Insert new choice.
       db_query("INSERT INTO {advpoll_choices} (nid, label, vote_offset, writein) VALUES (%d, '%s', %d, 1)", $node->nid, check_plain($form_values['writein_choice']), $next_offset);
+
+      // Get newest choice id.
+      $next_cid = db_result(db_query("SELECT cid FROM {advpoll_choices} WHERE nid = %d AND label = '%s'", $node->nid, $form_values['writein_choice']));
       
       // Add vote
       $vote = new stdClass();
       $vote->value = $vote_value;
-      $vote->tag = $next_offset;
+      $vote->tag = $next_cid;
       $vote->value_type = 'option';
       $votes[] = $vote;
     }
@@ -1523,7 +1532,7 @@ function advpoll_writein_merge_form_subm
   }
 
   // Delete the merged choice.
-  db_query('DELETE FROM {advpoll_choices} WHERE vote_offset = %d', $form_values['source']);
+  db_query('DELETE FROM {advpoll_choices} WHERE cid = %d', $form_values['source']);
   votingapi_recalculate_results('advpoll', $form_values['nid']);
   drupal_set_message(t('Write-in merged.'));
   // Unset destination form element so that drupal_goto() doesn't use it
@@ -1566,7 +1575,7 @@ function advpoll_writein_promote_form($n
 
 function advpoll_writein_promote_form_submit($form_id, $form_values) {
   if (count($form_values['promote'])) {
-    db_query('UPDATE {advpoll_choices} SET writein = 0 WHERE nid = %d AND vote_offset IN(%s)', $form_values['nid'], check_plain(implode(', ', $form_values['promote'])));
+    db_query('UPDATE {advpoll_choices} SET writein = 0 WHERE nid = %d AND cid IN(%s)', $form_values['nid'], check_plain(implode(', ', $form_values['promote'])));
     drupal_set_message(format_plural(count($form_values['promote']), 'Write-in promoted.', 'Write-ins promoted.'));
   }
   drupal_goto('node/'. $form_values['nid']);
Index: modes/binary.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/advpoll/modes/binary.inc,v
retrieving revision 1.7.2.30
diff -u -p -r1.7.2.30 binary.inc
--- modes/binary.inc	24 Nov 2007 19:21:57 -0000	1.7.2.30
+++ modes/binary.inc	24 Nov 2007 23:35:21 -0000
@@ -315,7 +315,7 @@ function advpoll_cancel_binary($node, $u
         $count = db_result(db_query('SELECT COUNT(1) FROM {votingapi_vote} WHERE content_id = %d AND tag = %d', $node->nid, $vote->tag));
         if ($count == 0) {
           // Delete the write-in because no one else voted for it.
-          db_query('DELETE FROM {advpoll_choices} WHERE vote_offset = %d AND nid = %d', $vote->tag, $node->nid);
+          db_query('DELETE FROM {advpoll_choices} WHERE cid = %d', $vote->tag);
           $recalculate = TRUE;
         }
       }
Index: modes/ranking.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/advpoll/modes/ranking.inc,v
retrieving revision 1.8.2.35
diff -u -p -r1.8.2.35 ranking.inc
--- modes/ranking.inc	24 Nov 2007 19:21:57 -0000	1.8.2.35
+++ modes/ranking.inc	24 Nov 2007 23:35:22 -0000
@@ -774,7 +774,7 @@ function advpoll_cancel_ranking($node, $
         $count = db_result(db_query('SELECT COUNT(1) FROM {votingapi_vote} WHERE content_id = %d AND tag = %d', $node->nid, $vote->tag));
         if ($count == 0) {
           // Delete the write-in because no one else voted for it.
-          db_query('DELETE FROM {advpoll_choices} WHERE vote_offset = %d AND nid = %d', $vote->tag, $node->nid);
+          db_query('DELETE FROM {advpoll_choices} WHERE cid = %d', $vote->tag);
           $recalculate = TRUE;
           watchdog('content', t('Removed write-in choice %choice after the last vote was cancelled.', array('%choice' => $node->choice[$vote->tag]['label'])));
         }
