? uuid_replication_3.patch
? uuid_replication_4.patch
? uuid_replication_5.patch
Index: uuid.admin.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/uuid/uuid.admin.inc,v
retrieving revision 1.1.2.4
diff -u -r1.1.2.4 uuid.admin.inc
--- uuid.admin.inc	19 Mar 2010 08:10:13 -0000	1.1.2.4
+++ uuid.admin.inc	19 Mar 2010 23:33:10 -0000
@@ -35,7 +35,7 @@
     ),
     '#description' => t('Should UUIDs be created automatically for users?'),
   );
-  
+
   $form['taxonomy'] = array(
     '#type' => 'fieldset',
     '#title' => t('Taxonomy settings'),
@@ -47,7 +47,7 @@
       '#title' => t('Automatic UUID generation for taxonomy'),
       '#default_value' => variable_get('uuid_automatic_for_taxonomy', array()),
       '#options' => $options,
-      '#description' => t("UUIDs will be created for the vocabulary and it's terms."),
+      '#description' => t("UUIDs will be created for the vocabulary and its terms."),
       '#required' => FALSE,
     );
   }
@@ -76,25 +76,47 @@
  * Ensure all content and users have UUIDs, if they are supposed to.
  */
 function uuid_sync() {
-  // Users.
   if (variable_get('uuid_automatic_for_users', FALSE)) {
-    db_query("INSERT INTO {uuid_users} SELECT u.uid, UUID() FROM {users} AS u WHERE NOT EXISTS (SELECT uid FROM {uuid_users} WHERE uid = u.uid)");
+    $result = db_query("SELECT uid FROM {users} WHERE uid NOT IN (SELECT uid FROM {uuid_users})");
+    while($item = db_fetch_object($result)) {
+      db_query("INSERT INTO {uuid_users} (uid, uuid) VALUES(%d, '%s')", $item->uid, uuid_uuid());
+    }
   }
 
-  // Nodes.
   foreach (variable_get('uuid_automatic_for_nodes', array()) as $type) {
-    db_query("INSERT INTO {uuid_node} SELECT n.nid, UUID() FROM {node} AS n WHERE n.type = '%s' AND NOT EXISTS (SELECT nid FROM {uuid_node} WHERE nid = n.nid)", $type);
-    db_query("INSERT INTO {uuid_node_revisions} SELECT nr.vid, UUID() FROM {node_revisions} AS nr INNER JOIN {node} n ON nr.nid = n.nid WHERE n.type = '%s' AND NOT EXISTS (SELECT vid FROM {uuid_node_revisions} WHERE vid = nr.vid)", $type);
+    // Slightly ugly, but it does save some queries for
+    // all the node types on which we don't want a UUID.
+    if ($type == '0')
+      continue;
+
+    // Nodes
+    $result = db_query("SELECT nid FROM {node} WHERE type = '%s' AND nid NOT IN (SELECT nid FROM {uuid_node})", $type);
+    while ($item = db_fetch_object($result)) {
+      db_query("INSERT INTO {uuid_node} (nid, uuid) VALUES(%d, '%s')", $item->nid, uuid_uuid());
+    }
+
+    // Revisions
+    $result = db_query("SELECT nr.vid AS vid FROM {node_revisions} AS nr INNER JOIN {node} n ON nr.nid = n.nid WHERE n.type = '%s' AND nr.vid NOT IN(SELECT vid FROM {uuid_node_revisions})", $type);
+    while ($item = db_fetch_object($result)) {
+      db_query("INSERT INTO {uuid_node_revisions} (vid, uuid) VALUES(%d, '%s')", $item->vid, uuid_uuid());
+    }
   }
 
-  // Taxonomy.
   $vids = variable_get('uuid_automatic_for_taxonomy', array());
   if ($vids) {
-    $placehoders = implode(', ', array_fill(0, count($vids), '%d'));
-    // Vocabularies.
-    db_query("INSERT INTO {uuid_vocabulary} SELECT v.vid, UUID() FROM {vocabulary} AS v WHERE v.vid IN ($placehoders) AND NOT EXISTS (SELECT vid FROM {uuid_vocabulary} WHERE vid = v.vid)", $vids);
-    // Terms.
-    db_query("INSERT INTO {uuid_term_data} SELECT td.tid, UUID() FROM {term_data} AS td WHERE td.vid IN ($placehoders) AND NOT EXISTS (SELECT tid FROM {uuid_term_data} WHERE tid = td.tid)", $vids);
+    $placeholders = implode(', ', array_fill(0, count($vids), '%d'));
+
+    // Vocabularies
+    $result = db_query("SELECT v.vid FROM {vocabulary} AS v WHERE v.vid IN ($placeholders) AND NOT EXISTS (SELECT vid FROM {uuid_vocabulary} WHERE vid = v.vid)", $vids);
+    while ($item = db_fetch_object($result)) {
+      db_query("INSERT INTO {uuid_vocabulary} (vid, uuid) VALUES(%d, '%s')", $item->vid, uuid_uuid());
+    }
+
+    // Terms
+    $result = db_query("SELECT td.tid FROM {term_data} AS td WHERE td.vid IN ($placeholders) AND NOT EXISTS (SELECT tid FROM {uuid_term_data} WHERE tid = td.tid)", $vids);
+    while ($item = db_fetch_object($result)) {
+      db_query("INSERT INTO {uuid_term_data} (tid, uuid) VALUES(%d, '%s')", $item->tid, uuid_uuid());
+    }
   }
 
   drupal_set_message(t("UUID tables have been updated."));
Index: uuid.install
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/uuid/uuid.install,v
retrieving revision 1.1.2.5
diff -u -r1.1.2.5 uuid.install
--- uuid.install	19 Mar 2010 07:38:22 -0000	1.1.2.5
+++ uuid.install	19 Mar 2010 23:33:10 -0000
@@ -57,8 +57,8 @@
       ),
     ),
     'primary key' => array($key),
-    'indexes' => array(
-      'uuid_'. $table .'_uuid_idx' => array('uuid'),
+    'unique keys' => array(
+      'uuid_'. $table .'_uuid_key' => array('uuid'),
     ),
   );
 }
@@ -70,7 +70,7 @@
   variable_del('uuid_automatic_for_nodes');
   variable_del('uuid_automatic_for_users');
   variable_del('uuid_automatic_for_taxonomy');
-  
+
   // Remove tables.
   drupal_uninstall_schema('uuid');
 }
@@ -80,9 +80,26 @@
  */
 function uuid_update_6001() {
   $ret = array();
-  
+
   db_create_table($ret, 'uuid_vocabulary', uuid_table_schema('vocabulary', 'vid'));
   db_create_table($ret, 'uuid_term_data', uuid_table_schema('term_data', 'tid'));
-  
+
+  return $ret;
+}
+
+/**
+ * Implementation of hook_update().
+ *
+ * For each of out tables, drop the indexe on the UUID column and add
+ * a unique key on that column.
+ */
+function uuid_update_6002() {
+  $ret = array();
+
+  foreach (uuid_schema() as $table => $schema) {
+    db_drop_index($ret, $table, $table .'_uuid_idx');
+    db_add_unique_key($ret, $table, $table .'_uuid_key', array('uuid'));
+  }
+
   return $ret;
 }
Index: uuid.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/uuid/uuid.module,v
retrieving revision 1.1.2.7
diff -u -r1.1.2.7 uuid.module
--- uuid.module	19 Mar 2010 08:13:01 -0000	1.1.2.7
+++ uuid.module	19 Mar 2010 23:33:10 -0000
@@ -43,12 +43,12 @@
           db_query("INSERT INTO {uuid_node_revisions} (vid, uuid) VALUES (%d, '%s')", $node->vid, $node->revision_uuid);
         }
         else {
-          db_query("INSERT INTO {uuid_node_revisions} (vid, uuid) VALUES (%d, UUID())", $node->vid);
+          db_query("INSERT INTO {uuid_node_revisions} (vid, uuid) VALUES (%d, '%s')", $node->vid, uuid_uuid());
         }
       }
       else if (in_array($node->type, $automatic_types)) {
-        db_query('INSERT INTO {uuid_node} (nid, uuid) VALUES (%d, UUID())', $node->nid);
-        db_query('INSERT INTO {uuid_node_revisions} (vid, uuid) VALUES (%d, UUID())', $node->vid);
+        db_query("INSERT INTO {uuid_node} (nid, uuid) VALUES (%d, '%s')", $node->nid, uuid_uuid());
+        db_query("INSERT INTO {uuid_node_revisions} (vid, uuid) VALUES (%d, '%s')", $node->vid, uuid_uuid());
       }
       break;
     case 'update':
@@ -57,7 +57,7 @@
           db_query("INSERT INTO {uuid_node_revisions} (vid, uuid) VALUES (%d, '%s')", $node->vid, $node->revision_uuid);
         }
         else {
-          db_query("INSERT INTO {uuid_node_revisions} (vid, uuid) VALUES (%d, UUID())", $node->vid);
+          db_query("INSERT INTO {uuid_node_revisions} (vid, uuid) VALUES (%d, '%s')", $node->vid, uuid_uuid());
         }
       }
       break;
@@ -127,7 +127,7 @@
         db_query("INSERT INTO {uuid_users} (uid, uuid) VALUES (%d, '%s')", $user->uid, $user->uuid);
       }
       else if (variable_get('uuid_automatic_for_users', FALSE)) {
-        db_query('INSERT INTO {uuid_users} (uid, uuid) VALUES (%d, UUID())', $user->uid);
+        db_query("INSERT INTO {uuid_users} (uid, uuid) VALUES (%d, '%s')", $user->uid, uuid_uuid());
       }
       break;
     case 'update':
@@ -181,8 +181,8 @@
     $field = $types[$type]['field'];
     switch ($op) {
       case 'insert':
-        db_query("INSERT INTO {" . $types[$type]['table'] . "} ($field, uuid) VALUES (%d, UUID())",
-          $array[$types[$type]['field']]);
+        db_query("INSERT INTO {" . $types[$type]['table'] . "} ($field, uuid) VALUES (%d, '%s')",
+          $array[$types[$type]['field']], uuid_uuid());
         break;
       case 'delete':
         db_query("DELETE FROM {". $types[$type]['table'] ."} WHERE $field = %d", $array[$types[$type]['field']]);
@@ -197,3 +197,59 @@
 function uuid_is_valid($uuid) {
   return (boolean) preg_match('/^[A-Fa-f0-9]{8}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{12}$/', $uuid);
 }
+
+/**
+ * @return a Universally Unique IDentifier
+ */
+function uuid_uuid() {
+  // If we're not using postgres, the database will give us a UUID.
+  if ($GLOBALS['db_type'] != 'pgsql') {
+    return db_result(db_query('SELECT UUID()'));
+  }
+
+  // If the function provided by the uuid pecl extension is available, use that.
+  if(function_exists('uuid_create')) {
+    return uuid_create(UUID_TYPE_DEFAULT);
+  }
+
+  /**
+   * @desc  Generates a Universally Unique IDentifier, version 4.
+   * 
+   * RFC 4122 (http://www.ietf.org/rfc/rfc4122.txt) defines a special type of Globally
+   * Unique IDentifiers (GUID), as well as several methods for producing them. One
+   * such method, described in section 4.4, is based on truly random or pseudo-random
+   * number generators, and is therefore implementable in a language like PHP.
+   *
+   * We choose to produce pseudo-random numbers with the Mersenne Twister, and to always
+   * limit single generated numbers to 16 bits (ie. the decimal value 65535). That is
+   * because, even on 32-bit systems, PHP's RAND_MAX will often be the maximum *signed*
+   * value, with only the equivalent of 31 significant bits. Producing two 16-bit random
+   * numbers to make up a 32-bit one is less efficient, but guarantees that all 32 bits
+   * are random.
+   *
+   * The algorithm for version 4 UUIDs (ie. those based on random number generators)
+   * states that all 128 bits separated into the various fields (32 bits, 16 bits, 16 bits,
+   * 8 bits and 8 bits, 48 bits) should be random, except : (a) the version number should
+   * be the last 4 bits in the 3rd field, and (b) bits 6 and 7 of the 4th field should
+   * be 01. We try to conform to that definition as efficiently as possible, generating
+   * smaller values where possible, and minimizing the number of base conversions.
+   *
+   * @author      David Holmes <dholmes@cfdsoftware.net>
+   *
+   * @return  string  A UUID, made up of 32 hex digits and 4 hyphens.
+   *
+   * @see  http://php.net/manual/en/function.uniqid.php#65879
+   */
+
+  // The field names refer to RFC 4122 section 4.1.2
+  return sprintf('%04x%04x-%04x-%03x4-%04x-%04x%04x%04x',
+    mt_rand(0, 65535), mt_rand(0, 65535), // 32 bits for "time_low"
+    mt_rand(0, 65535), // 16 bits for "time_mid"
+    mt_rand(0, 4095),  // 12 bits before the 0100 of (version) 4 for "time_hi_and_version"
+    bindec(substr_replace(sprintf('%016b', mt_rand(0, 65535)), '01', 6, 2)),
+      // 8 bits, the last two of which (positions 6 and 7) are 01, for "clk_seq_hi_res"
+      // (hence, the 2nd hex digit after the 3rd hyphen can only be 1, 5, 9 or d)
+      // 8 bits for "clk_seq_low"
+    mt_rand(0, 65535), mt_rand(0, 65535), mt_rand(0, 65535) // 48 bits for "node" 
+  );
+}
