Index: uuid.admin.inc =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/uuid/Attic/uuid.admin.inc,v retrieving revision 1.1.2.2 diff -u -p -r1.1.2.2 uuid.admin.inc --- uuid.admin.inc 11 Jun 2009 18:07:13 -0000 1.1.2.2 +++ uuid.admin.inc 27 Jul 2009 17:00:10 -0000 @@ -56,13 +56,32 @@ function uuid_admin() { * Ensure all content and users have UUIDs, if they are supposed to. */ function uuid_sync() { + + // UUID() is non-deterministic and breaks with replication. + // To combat this we need to iterate through all items and statically set a uuid. 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()); + } } 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; + + $nid_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($nid_result)) { + db_query("INSERT INTO {uuid_node} (nid, uuid) VALUES(%d, '%s')", $item->nid, uuid_uuid()); + } + + $vid_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($vid_result)) { + db_query("INSERT INTO {uuid_node_revisions} (vid, uuid) VALUES(%d, '%s')", $item->vid, uuid_uuid()); + } } drupal_set_message(t("UUID tables have been updated.")); Index: uuid.module =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/uuid/uuid.module,v retrieving revision 1.1.2.4 diff -u -p -r1.1.2.4 uuid.module --- uuid.module 11 Jun 2009 18:07:13 -0000 1.1.2.4 +++ uuid.module 27 Jul 2009 17:00:10 -0000 @@ -36,28 +36,28 @@ function uuid_nodeapi(&$node, $op, $teas // Handle the case where automatic UUID generation is turned OFF but a // node is created, node_save(), intentionally with the $node->uuid // attribute. - if (isset($node->uuid) && uuid_is_valid($node->uuid)) { + if (isset($node->uuid) && uuid_uuid_is_valid($node->uuid)) { db_query("INSERT INTO {uuid_node} (nid, uuid) VALUES (%d, '%s')", $node->nid, $node->uuid); - if (isset($node->revision_uuid) && uuid_is_valid($node->revision_uuid)) { + if (isset($node->revision_uuid) && uuid_uuid_is_valid($node->revision_uuid)) { 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': if ($node->revision) { - if (isset($node->revision_uuid) && uuid_is_valid($node->revision_uuid)) { + if (isset($node->revision_uuid) && uuid_uuid_is_valid($node->revision_uuid)) { 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; @@ -123,7 +123,7 @@ function uuid_user($op, &$edit, &$user, $user->uuid = db_result(db_query('SELECT uuid FROM {uuid_users} WHERE uid = %d', $user->uid)); break; case 'insert': - if (isset($user->uuid) && uuid_is_valid($user->uuid)) { + if (isset($user->uuid) && uuid_uuid_is_valid($user->uuid)) { db_query("INSERT INTO {uuid_users} (uid, uuid) VALUES (%d, '%s')", $user->uid, $user->uuid); } else if (variable_get('uuid_automatic_for_users', FALSE)) { @@ -131,7 +131,7 @@ function uuid_user($op, &$edit, &$user, } break; case 'update': - if (isset($user->uuid) && uuid_is_valid($user->uuid)) { + if (isset($user->uuid) && uuid_uuid_is_valid($user->uuid)) { $exists = db_result(db_query('SELECT 1 FROM {uuid_users} WHERE uid = %d', $user->uid)); if (!$exists) { @@ -163,8 +163,39 @@ function user_get_by_uuid($uuid) { } /** + * Returns a new formatted UUID string. + * Blatantly copied from http://php.net/manual/en/function.uniqid.php#65879 + * + * @return $string + */ +function uuid_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); + } + + // 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" + ); +} + +/** * Determines if a UUID is valid. */ -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); +function uuid_uuid_is_valid($uuid) { + if (function_exists("uuid_is_valid")) { + $valid = uuid_is_valid($uuid); + } else { + $valid = 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 (boolean) $valid; }