within system.install, we are trying to insert some default setting values into some "serial" field, which will cause error in case of MSSQL. e.g.

<?php
db_query("INSERT INTO {users} (uid,name,mail) VALUES(0,'','')");
?>

details: in case of MSSQL, we can use IDENTITY(1, 1) for auto increment, when implementing "serial" field. by using this, we will also able to fetch session last inserted id by calling @@IDENTITY (please refer to http://drupal.org/node/74308#comment-289704). BTW, MSSQL don't allow manually insert value into such IDENTITY field; we will able to do so, unless explicitly unlock/lock table by setting INSERT_IDENTITY, which will not be a suitable solution for drupal...

suggestion: simply follow the rules of using "serial": always left its value as blank during INSERT, and let its auto generate feature function, even for system installation. we may UPDATE (or some other handling) its id after a complete INSERT. BTW, this also means we will "give up" the first id value. e.g. change the following (system.install:246) from:

<?php
  db_query("INSERT INTO {users} (uid,name,mail) VALUES(0,'','')");
?>

into:

<?php
  db_query("INSERT INTO {users} (name,mail) VALUES('','')");
  db_query("UPDATE {user} SET uid = 0 WHERE uid = 1");
?>

Comments

hswong3i’s picture

follow up: sorry that it is not even able to UPDATE an IDENTITY field in MSSQL:

INSERT INTO users ([name], [mail]) VALUES ('', '');

UPDATE users SET uid = 0 WHERE uid = 1;
Msg 8102, Level 16, State 1, Line 3
Cannot update identity column 'uid'.

we may need to find some other solutions... may be don't set the field as serial as default; after insert default system value, then change its type into serial manually?

hass’s picture

subscribe

hswong3i’s picture

Status: Active » Fixed

@killes: thanks for your information, as it is a similar case as MySQL:

<?php
    // As of Drupal 6, users.uid is an auto-incrementing column, but
    // previously it was not.  Below, we insert a row with uid 0 to
    // represent user anonymous.  By default, mysql treats that as
    // requesting the next sequence value which, of course, is uid
    // 1!  This statement turns off that behavior for the duration
    // of the current request, which is all we need.
    //
    // Note that this statement must be run any time the uid column
    // is inserted or altered.  That includes loading mysqldump
    // backups, but mysqldump puts this statement in all backups for
    // this exact reason.  It also includes any Schema API
    // table-altering operations on the users table.
    db_query("SET sql_mode = 'NO_AUTO_VALUE_ON_ZERO'");
?>

i will try for a similar handling for MSSQL, e.g.:

  switch ($GLOBALS['db_type']) {
    case 'mssql':
      // MS SQL don't allow manually insert value into IDENTITY, unless
      // setting IDENTITY_INSERT ON/OFF explicitly. Here we try to handle
      // this uid = 0 exceptional case by other method: manually set the
      // seed of IDENTITY into 0 before this insertion, so the sequence
      // will keeps correctly.
      db_query("DBCC CHECKIDENT({users}, RESEED, 0)");
      db_query("INSERT INTO {users} (name, mail) VALUES('%s', '%s')", '', '');
      break;
    default:
      db_query("INSERT INTO {users} (uid,name,mail) VALUES(0,'','')");
      break;
  }

Anonymous’s picture

Status: Fixed » Closed (fixed)