Index: uuid.admin.inc =================================================================== RCS file: /cvs/drupal/contributions/modules/uuid/uuid.admin.inc,v retrieving revision 1.1.2.2 diff -u -r1.1.2.2 uuid.admin.inc --- uuid.admin.inc 11 Jun 2009 18:07:13 -0000 1.1.2.2 +++ uuid.admin.inc 28 Aug 2009 16:36:39 -0000 @@ -57,12 +57,12 @@ */ function uuid_sync() { 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)"); + db_query("INSERT INTO {uuid_users} SELECT u.uid, '%s' FROM {users} AS u WHERE NOT EXISTS (SELECT uid FROM {uuid_users} WHERE uid = u.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); + db_query("INSERT INTO {uuid_node} SELECT n.nid, '%s' FROM {node} AS n WHERE n.type = '%s' AND NOT EXISTS (SELECT nid FROM {uuid_node} WHERE nid = n.nid)", uuid_uuid(), $type); + db_query("INSERT INTO {uuid_node_revisions} SELECT nr.vid, '%s' 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)", uuid_uuid(), $type); } drupal_set_message(t("UUID tables have been updated.")); Index: uuid.module =================================================================== RCS file: /cvs/drupal/contributions/modules/uuid/uuid.module,v retrieving revision 1.1.2.4 diff -u -r1.1.2.4 uuid.module --- uuid.module 11 Jun 2009 18:07:13 -0000 1.1.2.4 +++ uuid.module 28 Aug 2009 16:38:55 -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': @@ -168,3 +168,61 @@ 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 ($GLOBALS['db_type'] != 'pgsql') { + return db_result(db_query("SELECT UUID();")); + } + + /** + * @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. + * + * @copyright Copyright (c) CFD Labs, 2006. This function may be used freely for + * any purpose ; it is distributed without any form of warranty whatsoever. + * @author David Holmes + * + * @return string A UUID, made up of 32 hex digits and 4 hyphens. + * + * @see http://php.net/manual/en/function.uniqid.php#65879 + */ + + // 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" + ); +} +