You are here

public function Schema::addField in Drupal driver for SQL Server and SQL Azure 8

Same name and namespace in other branches
  1. 8.2 drivers/lib/Drupal/Driver/Database/sqlsrv/Schema.php \Drupal\Driver\Database\sqlsrv\Schema::addField()
  2. 3.0.x drivers/lib/Drupal/Driver/Database/sqlsrv/Schema.php \Drupal\Driver\Database\sqlsrv\Schema::addField()

Override DatabaseSchema::addField().

@status complete

Overrides Schema::addField

1 call to Schema::addField()
Schema::changeField in drivers/lib/Drupal/Driver/Database/sqlsrv/Schema.php
Override DatabaseSchema::changeField().

File

drivers/lib/Drupal/Driver/Database/sqlsrv/Schema.php, line 956
Definition of Drupal\Driver\Database\sqlsrv\Schema

Class

Schema

Namespace

Drupal\Driver\Database\sqlsrv

Code

public function addField($table, $field, $spec, $new_keys = array()) {
  if (!$this
    ->tableExists($table, TRUE)) {
    throw new DatabaseSchemaObjectDoesNotExistException(t("Cannot add field %table.%field: table doesn't exist.", array(
      '%field' => $field,
      '%table' => $table,
    )));
  }
  if ($this
    ->fieldExists($table, $field)) {
    throw new DatabaseSchemaObjectExistsException(t("Cannot add field %table.%field: field already exists.", array(
      '%field' => $field,
      '%table' => $table,
    )));
  }

  /** @var Transaction $transaction */
  $transaction = $this->connection
    ->startTransaction(NULL, DatabaseTransactionSettings::GetDDLCompatibleDefaults());

  // Prepare the specifications.
  $spec = $this
    ->processField($spec);

  // Use already prefixed table name.
  $table_prefixed = $this->connection
    ->prefixTables('{' . $table . '}');

  // If the field is declared NOT NULL, we have to first create it NULL insert
  // the initial data (or populate default values) and then switch to NOT NULL.
  $fixnull = FALSE;
  if (!empty($spec['not null'])) {
    $fixnull = TRUE;
    $spec['not null'] = FALSE;
  }

  // Create the field.
  // Because the default values of fields can contain string literals
  // with braces, we CANNOT allow the driver to prefix tables because the algorithm
  // to do so is a crappy str_replace.
  $query = "ALTER TABLE {$table_prefixed} ADD ";
  $query .= $this
    ->createFieldSql($table, $field, $spec);
  $this->connection
    ->query_direct($query, array(), array(
    'prefix_tables' => FALSE,
  ));

  // Load the initial data.
  if (isset($spec['initial'])) {
    $this->connection
      ->update($table)
      ->fields(array(
      $field => $spec['initial'],
    ))
      ->execute();
  }

  // Switch to NOT NULL now.
  if ($fixnull === TRUE) {

    // There is no warranty that the old data did not have NULL values, we need to populate
    // nulls with the default value because this won't be done by MSSQL by default.
    if (!empty($spec['default'])) {
      $default_expression = $this
        ->defaultValueExpression($spec['sqlsrv_type'], $spec['default']);
      $this->connection
        ->query_direct("UPDATE [{{$table}}] SET [{$field}] = {$default_expression} WHERE [{$field}] IS NULL");
    }

    // Now it's time to make this non-nullable.
    $spec['not null'] = TRUE;
    $this->connection
      ->query_direct('ALTER TABLE {' . $table . '} ALTER COLUMN ' . $this
      ->createFieldSql($table, $field, $spec, TRUE));
  }

  // Add the new keys.
  if (isset($new_keys)) {
    $this
      ->recreateTableKeys($table, $new_keys);
  }

  // Commit.
  $transaction
    ->commit();
}