? uuid_replication_6.patch.txt ? uuid_replication_7.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 1 Apr 2010 23:49:36 -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, ); } @@ -78,23 +78,50 @@ 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); + $types = variable_get('uuid_automatic_for_nodes', array()); + + // Remove disabled node types. + $types = array_filter($types); + if (!empty($types)) { + $placeholders = db_placeholders($types, 'varchar'); + + // Nodes. + $result = db_query("SELECT nid FROM {node} WHERE type IN (" . $placeholders . ") AND nid NOT IN (SELECT nid FROM {uuid_node})", $types); + 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 IN (" . $placeholders . ") AND nr.vid NOT IN (SELECT vid FROM {uuid_node_revisions})", $types); + 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()); + + // Remove disabled vocabularies. + $vids = array_filter($vids); if ($vids) { - $placehoders = implode(', ', array_fill(0, count($vids), '%d')); + $placeholders = db_placeholders($vids, 'int'); + // 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); + $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. - 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); + $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 1 Apr 2010 23:49:36 -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.8 diff -u -r1.1.2.8 uuid.module --- uuid.module 1 Apr 2010 08:33:05 -0000 1.1.2.8 +++ uuid.module 1 Apr 2010 23:49:36 -0000 @@ -2,7 +2,7 @@ // $Id: uuid.module,v 1.1.2.8 2010/04/01 08:33:05 recidive Exp $ /** - * Implementation of hook_menu() + * Implementation of hook_menu(). */ function uuid_menu() { $items = array(); @@ -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); } + +/** + * Generate and return an Universally Unique IDentifier (UUID). + */ +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 + * + * @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" + ); +}