When I try to enable block_class module (http://drupal.org/project/block_class), the following error occurs:

PDOException: SQLSTATE[42000]: [Microsoft][SQL Server Native Client 10.0][SQL Server]Cannot use duplicate column names in index. Column name 'Array' listed more than once.: CREATE TABLE [{block_class}] ( [module] nvarchar(255) NOT NULL CONSTRAINT {block_class}_module_df DEFAULT '', [delta] nvarchar(255) NOT NULL CONSTRAINT {block_class}_delta_df DEFAULT '', [css_class] nvarchar(255) NOT NULL CONSTRAINT {block_class}_css_class_df DEFAULT '', CONSTRAINT {block_class}_pkey PRIMARY KEY CLUSTERED ([Array], [Array]) ); Array ( ) in db_create_table() (line 2686 of D:\work\jandenul\includes\database\database.inc).

It is caused by wrong installation schema handling. If I'm not mistaking, Microsoft SQL doesn't allow explicitly set index prefix length. As it is specified in docs (http://drupal.org/node/146939):

'primary key': An array of one or more key column specifers that form the primary key.
A key column specifier is either a string naming a field or an array of two elements, a string naming a field and an integer prefix length. If a prefix length is specified, only that many bytes or characters of the named field are used as part of the key. If the database engine does not support this optimization, the prefix length is ignored.

I have no time to provide consistent patch, but will suggest a fix right here (apply to sqlsrv/schema.inc):

  protected function createTableSql($name, $table) {
    $sql_fields = array();
    foreach ($table['fields'] as $field_name => $field) {
      $sql_fields[] = $this->createFieldSql($name, $field_name, $this->processField($field));
    }

    // If the table has no primary key, create one for us.
    // TODO: only necessary on Azure.
    if (isset($table['primary key']) && is_array($table['primary key'])) {
      $primary_key = array();
      foreach ($table['primary key'] as $key) {
        if (is_array($key)) {
          $primary_key[] = $key[0];
        }
        else {
          $primary_key[] = $key;
        }
      }
      $sql_fields[] = 'CONSTRAINT {' . $name . '}_pkey PRIMARY KEY CLUSTERED (' . implode(', ', $this->connection->quoteIdentifiers($primary_key)) . ')';
    }
    else {

Comments

damien tournoud’s picture

Title: PDOException: SQLSTATE[42000]: [Microsoft][SQL Server Native Client 10.0][SQL Server]Cannot use duplicate column names in index. » Do not use length specifiers in a primary key
Project: Drupal driver for SQL Server and SQL Azure » Block Class
Component: Schema handling » Code
Status: Needs review » Active

We cannot support length specifiers in primary keys, and as far as I know only the MySQL driver does support this. The suggested fix is absolutely not appropriate: we cannot change the definition of the primary key, or its unique constraint will be different on SQL Server then on MySQL :)

This is a sign of a badly designed database schema, so this will have to be fixed in the Block Class module.

berenddeboer’s picture

Status: Active » Closed (fixed)

I think this is no longer appropriate, length specifiers have been removed from the block class code.