From bae3e31e1fc1fb8e546edd6ccea108dc9689c000 Mon Sep 17 00:00:00 2001
From: Alex Pott <alex.a.pott@googlemail.com>
Date: Fri, 24 Jun 2016 18:26:50 +0200
Subject: [PATCH] Issue #2753475 by amateescu, timmillwood: Support using the
 values of another field as initial values when adding a new field

---
 .../Drupal/Core/Database/Driver/mysql/Schema.php  |  5 +++++
 .../Drupal/Core/Database/Driver/pgsql/Schema.php  |  5 +++++
 .../Drupal/Core/Database/Driver/sqlite/Schema.php | 12 ++++++++++++
 core/lib/Drupal/Core/Database/Schema.php          |  2 ++
 .../KernelTests/Core/Database/SchemaTest.php      | 15 +++++++++++++++
 5 files changed, 39 insertions(+)

diff --git a/core/lib/Drupal/Core/Database/Driver/mysql/Schema.php b/core/lib/Drupal/Core/Database/Driver/mysql/Schema.php
index 107495bea6c9..6fd999e28025 100644
--- a/core/lib/Drupal/Core/Database/Driver/mysql/Schema.php
+++ b/core/lib/Drupal/Core/Database/Driver/mysql/Schema.php
@@ -411,6 +411,11 @@ public function addField($table, $field, $spec, $keys_new = array()) {
         ->fields(array($field => $spec['initial']))
         ->execute();
     }
+    if (isset($spec['initial_from_field'])) {
+      $this->connection->update($table)
+        ->expression($field, $spec['initial_from_field'])
+        ->execute();
+    }
     if ($fixnull) {
       $spec['not null'] = TRUE;
       $this->changeField($table, $field, $field, $spec);
diff --git a/core/lib/Drupal/Core/Database/Driver/pgsql/Schema.php b/core/lib/Drupal/Core/Database/Driver/pgsql/Schema.php
index 4cd660b4b42b..c0775c914aff 100644
--- a/core/lib/Drupal/Core/Database/Driver/pgsql/Schema.php
+++ b/core/lib/Drupal/Core/Database/Driver/pgsql/Schema.php
@@ -531,6 +531,11 @@ public function addField($table, $field, $spec, $new_keys = array()) {
         ->fields(array($field => $spec['initial']))
         ->execute();
     }
+    if (isset($spec['initial_from_field'])) {
+      $this->connection->update($table)
+        ->expression($field, $spec['initial_from_field'])
+        ->execute();
+    }
     if ($fixnull) {
       $this->connection->query("ALTER TABLE {" . $table . "} ALTER $field SET NOT NULL");
     }
diff --git a/core/lib/Drupal/Core/Database/Driver/sqlite/Schema.php b/core/lib/Drupal/Core/Database/Driver/sqlite/Schema.php
index a3c001cc846e..4b954ed35dfe 100644
--- a/core/lib/Drupal/Core/Database/Driver/sqlite/Schema.php
+++ b/core/lib/Drupal/Core/Database/Driver/sqlite/Schema.php
@@ -316,6 +316,11 @@ public function addField($table, $field, $specification, $keys_new = array()) {
           ->fields(array($field => $specification['initial']))
           ->execute();
       }
+      if (isset($specification['initial_from_field'])) {
+        $this->connection->update($table)
+          ->expression($field, $specification['initial_from_field'])
+          ->execute();
+      }
     }
     else {
       // We cannot add the field directly. Use the slower table alteration
@@ -335,6 +340,13 @@ public function addField($table, $field, $specification, $keys_new = array()) {
           'arguments' => array(':newfieldinitial' => $specification['initial']),
         );
       }
+      elseif (isset($specification['initial_from_field'])) {
+        // If we have a initial value, copy it over.
+        $mapping[$field] = array(
+          'expression' => $specification['initial_from_field'],
+          'arguments' => [],
+        );
+      }
       else {
         // Else use the default of the field.
         $mapping[$field] = NULL;
diff --git a/core/lib/Drupal/Core/Database/Schema.php b/core/lib/Drupal/Core/Database/Schema.php
index 1a2141575ac7..8b9eb7e129dd 100644
--- a/core/lib/Drupal/Core/Database/Schema.php
+++ b/core/lib/Drupal/Core/Database/Schema.php
@@ -305,6 +305,8 @@ abstract public function dropTable($table);
    *   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.
    * @param $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
diff --git a/core/tests/Drupal/KernelTests/Core/Database/SchemaTest.php b/core/tests/Drupal/KernelTests/Core/Database/SchemaTest.php
index 7866146f90b8..8641fd3c9cc4 100644
--- a/core/tests/Drupal/KernelTests/Core/Database/SchemaTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Database/SchemaTest.php
@@ -505,6 +505,7 @@ function testSchemaAddField() {
           array('not null' => FALSE, 'default' => 7),
           array('not null' => TRUE, 'initial' => 1),
           array('not null' => TRUE, 'initial' => 1, 'default' => 7),
+          array('not null' => TRUE, 'initial_from_field' => 'serial_column'),
         );
 
         foreach ($variations as $variation) {
@@ -532,6 +533,7 @@ function testSchemaAddField() {
           array('not null' => FALSE, 'default' => 7),
           array('not null' => TRUE, 'initial' => 1),
           array('not null' => TRUE, 'initial' => 1, 'default' => 7),
+          array('not null' => TRUE, 'initial_from_field' => 'serial_column'),
         );
 
         foreach ($variations as $variation) {
@@ -620,6 +622,19 @@ protected function assertFieldCharacteristics($table_name, $field_name, $field_s
       $this->assertEqual($count, 0, 'Initial values filled out.');
     }
 
+    // Check that the initial value from another field has been registered.
+    if (isset($field_spec['initial_from_field'])) {
+      // There should be no row with a value different than
+      // $field_spec['initial_from_field'].
+      $count = db_select($table_name)
+        ->fields($table_name, array('serial_column'))
+        ->where($table_name . '.' . $field_spec['initial_from_field'] . ' <> ' . $table_name . '.' . $field_name)
+        ->countQuery()
+        ->execute()
+        ->fetchField();
+      $this->assertEqual($count, 0, 'Initial values from another field filled out.');
+    }
+
     // Check that the default value has been registered.
     if (isset($field_spec['default'])) {
       // Try inserting a row, and check the resulting value of the new column.
-- 
GitLab