Index: schema.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/sqlsrv/schema.inc,v
retrieving revision 1.4
diff -u -p -r1.4 schema.inc
--- schema.inc	20 Aug 2010 16:09:58 -0000	1.4
+++ schema.inc	14 Jan 2011 16:19:45 -0000
@@ -67,7 +67,7 @@ class DatabaseSchema_sqlsrv extends Data
 
       if (isset($table['unique keys']) && is_array($table['unique keys'])) {
         foreach ($table['unique keys'] as $key_name => $key) {
-          $this->connection->query($this->addUniqueKeySql($name, $key_name, $key));
+          $this->addUniqueKey($name, $key_name, $key);
         }
       }
     }
@@ -568,24 +568,6 @@ class DatabaseSchema_sqlsrv extends Data
   }
 
   /**
-   * Build the SQL for the creation of an unique key.
-   *
-   * @status tested
-   */
-  protected function addUniqueKeySql($table, $name, $fields) {
-    // Build a condition.
-    $conditions = array();
-    foreach ($fields as $field) {
-      if (is_array($field)) {
-        $field = $field[0];
-      }
-      $conditions[] = '[' . $field . '] IS NOT NULL';
-    }
-
-    return 'CREATE UNIQUE INDEX ' . $name . '_unique ON [{' . $table . '}] (' . $this->createKeySql($fields) . ') WHERE ' . implode(' AND ', $conditions);
-  }
-
-  /**
    * Override DatabaseSchema::addUniqueKey().
    *
    * @status tested
@@ -598,9 +580,29 @@ class DatabaseSchema_sqlsrv extends Data
       throw new DatabaseSchemaObjectExistsException(t("Cannot add unique key %name to table %table: unique key already exists.", array('%table' => $table, '%name' => $name)));
     }
 
-    echo $this->addUniqueKeySql($table, $name, $fields);
+    // First, build a GUID key for the table if necessary.
+    if (!$this->fieldExists($table, '_technical_pk')) {
+      $this->connection->query('ALTER TABLE {' . $table . '} ADD _technical_pk UNIQUEIDENTIFIER DEFAULT NEWID()');
+    }
+
+    // Then, build a expression based on the columns.
+    $column_expression = array();
+    foreach ($fields as $field) {
+      if (is_array($field)) {
+        $column_expression[] = 'SUBSTRING(CAST(' . $field[0] . ' AS varbinary),1,' . $field[1] . ')';
+      }
+      else {
+        $column_expression[] = 'CAST(' . $field . ' AS varbinary)';
+      }
+    }
+    $column_expression = implode(' + ', $column_expression);
 
-    $this->connection->query($this->addUniqueKeySql($table, $name, $fields));
+    // Build a computed column based on the expression that replaces NULL
+    // values with the globally unique identifier generated previously.
+    // This is (very) unlikely to result in a collision with any actual value
+    // in the columns of the unique key.
+    $this->connection->query('ALTER TABLE {' . $table . '} ADD _technical_unique_' . $name . " AS CAST(HashBytes('MD4', COALESCE(" . $column_expression . ", CAST(_technical_pk AS varbinary))) AS varbinary(16))");
+    $this->connection->query('CREATE UNIQUE INDEX ' . $name . '_unique ON [{' . $table . '}] (_technical_unique_' . $name . ')');
   }
 
   /**
@@ -614,6 +616,14 @@ class DatabaseSchema_sqlsrv extends Data
     }
 
     $this->connection->query('DROP INDEX ' . $name . '_unique ON [{' . $table . '}]');
+    $this->connection->query('ALTER TABLE [{' . $table . '}] DROP COLUMN _technical_unique_' . $name);
+
+    // Get the number of remaining unique indexes on the table, and prune
+    // the technical primary key if possible.
+    $unique_indexes = $this->connection->query('SELECT COUNT(*) FROM sys.indexes WHERE object_id = OBJECT_ID(:table) AND is_unique = 1', array(':table' => $this->connection->prefixTables('{' . $table . '}')))->fetchField();
+    if (!$unique_indexes) {
+      $this->dropField($table, '_technical_pk');
+    }
   }
 
   /**
