You are here

public function Schema::addField in Drupal 9

Same name in this branch
  1. 9 core/lib/Drupal/Core/Database/Schema.php \Drupal\Core\Database\Schema::addField()
  2. 9 core/lib/Drupal/Core/Database/Driver/sqlite/Schema.php \Drupal\Core\Database\Driver\sqlite\Schema::addField()
  3. 9 core/lib/Drupal/Core/Database/Driver/pgsql/Schema.php \Drupal\Core\Database\Driver\pgsql\Schema::addField()
  4. 9 core/lib/Drupal/Core/Database/Driver/mysql/Schema.php \Drupal\Core\Database\Driver\mysql\Schema::addField()
  5. 9 core/tests/fixtures/database_drivers/module/corefake/src/Driver/Database/corefakeWithAllCustomClasses/Schema.php \Drupal\corefake\Driver\Database\corefakeWithAllCustomClasses\Schema::addField()
Same name and namespace in other branches
  1. 8 core/lib/Drupal/Core/Database/Driver/pgsql/Schema.php \Drupal\Core\Database\Driver\pgsql\Schema::addField()

Add a new field to a table.

Parameters

$table: Name of the table to be altered.

$field: Name of the field to be added.

$spec: The field specification array, as taken from a schema definition. The specification may also contain the key 'initial', the newly created field will be set to the value of the key in all rows. This is most useful for creating NOT NULL columns with no default value in existing tables. Alternatively, the 'initial_form_field' key may be used, which will auto-populate the new field with values from the specified field.

$keys_new: (optional) Keys and indexes specification to be created on the table along with adding the field. The format is the same as a table specification but without the 'fields' element. If you are adding a type 'serial' field, you MUST specify at least one key or index including it in this array. See ::changeField() for more explanation why.

Throws

\Drupal\Core\Database\SchemaObjectDoesNotExistException If the specified table doesn't exist.

\Drupal\Core\Database\SchemaObjectExistsException If the specified table already has a field by that name.

Overrides Schema::addField

File

core/lib/Drupal/Core/Database/Driver/pgsql/Schema.php, line 640

Class

Schema
PostgreSQL implementation of \Drupal\Core\Database\Schema.

Namespace

Drupal\Core\Database\Driver\pgsql

Code

public function addField($table, $field, $spec, $new_keys = []) {
  if (!$this
    ->tableExists($table)) {
    throw new SchemaObjectDoesNotExistException("Cannot add field '{$table}.{$field}': table doesn't exist.");
  }
  if ($this
    ->fieldExists($table, $field)) {
    throw new SchemaObjectExistsException("Cannot add field '{$table}.{$field}': field already exists.");
  }

  // Fields that are part of a PRIMARY KEY must be added as NOT NULL.
  $is_primary_key = isset($new_keys['primary key']) && in_array($field, $new_keys['primary key'], TRUE);
  if ($is_primary_key) {
    $this
      ->ensureNotNullPrimaryKey($new_keys['primary key'], [
      $field => $spec,
    ]);
  }
  $fixnull = FALSE;
  if (!empty($spec['not null']) && !isset($spec['default']) && !$is_primary_key) {
    $fixnull = TRUE;
    $spec['not null'] = FALSE;
  }
  $query = 'ALTER TABLE {' . $table . '} ADD COLUMN ';
  $query .= $this
    ->createFieldSql($field, $this
    ->processField($spec));
  $this->connection
    ->query($query);
  if (isset($spec['initial_from_field'])) {
    if (isset($spec['initial'])) {
      $expression = 'COALESCE(' . $spec['initial_from_field'] . ', :default_initial_value)';
      $arguments = [
        ':default_initial_value' => $spec['initial'],
      ];
    }
    else {
      $expression = $spec['initial_from_field'];
      $arguments = [];
    }
    $this->connection
      ->update($table)
      ->expression($field, $expression, $arguments)
      ->execute();
  }
  elseif (isset($spec['initial'])) {
    $this->connection
      ->update($table)
      ->fields([
      $field => $spec['initial'],
    ])
      ->execute();
  }
  if ($fixnull) {
    $this->connection
      ->query("ALTER TABLE {" . $table . "} ALTER {$field} SET NOT NULL");
  }
  if (isset($new_keys)) {

    // Make sure to drop the existing primary key before adding a new one.
    // This is only needed when adding a field because this method, unlike
    // changeField(), is supposed to handle primary keys automatically.
    if (isset($new_keys['primary key']) && $this
      ->constraintExists($table, 'pkey')) {
      $this
        ->dropPrimaryKey($table);
    }
    $this
      ->_createKeys($table, $new_keys);
  }

  // Add column comment.
  if (!empty($spec['description'])) {
    $this->connection
      ->query('COMMENT ON COLUMN {' . $table . '}.' . $field . ' IS ' . $this
      ->prepareComment($spec['description']));
  }
  $this
    ->resetTableInformation($table);
}