Updated Drupal to 8.6. This goes with the following updates because it's possible...
[yaffs-website] / web / core / lib / Drupal / Core / Database / Driver / sqlite / Schema.php
index e11c6da34e495b7e9377852ee369cab3542cfcca..0f0886c73c0df17faeac376eb682e0e08e529248 100644 (file)
@@ -2,7 +2,6 @@
 
 namespace Drupal\Core\Database\Driver\sqlite;
 
-use Drupal\Component\Utility\Unicode;
 use Drupal\Core\Database\SchemaObjectExistsException;
 use Drupal\Core\Database\SchemaObjectDoesNotExistException;
 use Drupal\Core\Database\Schema as DatabaseSchema;
@@ -53,6 +52,10 @@ class Schema extends DatabaseSchema {
    *   An array of SQL statements to create the table.
    */
   public function createTableSql($name, $table) {
+    if (!empty($table['primary key']) && is_array($table['primary key'])) {
+      $this->ensureNotNullPrimaryKey($table['primary key'], $table['fields']);
+    }
+
     $sql = [];
     $sql[] = "CREATE TABLE {" . $name . "} (\n" . $this->createColumnsSql($name, $table) . "\n)\n";
     return array_merge($sql, $this->createIndexSql($name, $table));
@@ -131,7 +134,7 @@ class Schema extends DatabaseSchema {
     // Set the correct database-engine specific datatype.
     // In case one is already provided, force it to uppercase.
     if (isset($field['sqlite_type'])) {
-      $field['sqlite_type'] = Unicode::strtoupper($field['sqlite_type']);
+      $field['sqlite_type'] = mb_strtoupper($field['sqlite_type']);
     }
     else {
       $map = $this->getFieldTypeMap();
@@ -316,6 +319,9 @@ class Schema extends DatabaseSchema {
     if ($this->fieldExists($table, $field)) {
       throw new SchemaObjectExistsException(t("Cannot add field @table.@field: field already exists.", ['@field' => $field, '@table' => $table]));
     }
+    if (isset($keys_new['primary key']) && in_array($field, $keys_new['primary key'], TRUE)) {
+      $this->ensureNotNullPrimaryKey($keys_new['primary key'], [$field => $specification]);
+    }
 
     // SQLite doesn't have a full-featured ALTER TABLE statement. It only
     // supports adding new fields to a table, in some simple cases. In most
@@ -327,14 +333,22 @@ class Schema extends DatabaseSchema {
       $this->connection->query($query);
 
       // Apply the initial value if set.
-      if (isset($specification['initial'])) {
+      if (isset($specification['initial_from_field'])) {
+        if (isset($specification['initial'])) {
+          $expression = 'COALESCE(' . $specification['initial_from_field'] . ', :default_initial_value)';
+          $arguments = [':default_initial_value' => $specification['initial']];
+        }
+        else {
+          $expression = $specification['initial_from_field'];
+          $arguments = [];
+        }
         $this->connection->update($table)
-          ->fields([$field => $specification['initial']])
+          ->expression($field, $expression, $arguments)
           ->execute();
       }
-      if (isset($specification['initial_from_field'])) {
+      elseif (isset($specification['initial'])) {
         $this->connection->update($table)
-          ->expression($field, $specification['initial_from_field'])
+          ->fields([$field => $specification['initial']])
           ->execute();
       }
     }
@@ -349,18 +363,26 @@ class Schema extends DatabaseSchema {
 
       // Build the mapping between the old fields and the new fields.
       $mapping = [];
-      if (isset($specification['initial'])) {
+      if (isset($specification['initial_from_field'])) {
         // If we have a initial value, copy it over.
+        if (isset($specification['initial'])) {
+          $expression = 'COALESCE(' . $specification['initial_from_field'] . ', :default_initial_value)';
+          $arguments = [':default_initial_value' => $specification['initial']];
+        }
+        else {
+          $expression = $specification['initial_from_field'];
+          $arguments = [];
+        }
         $mapping[$field] = [
-          'expression' => ':newfieldinitial',
-          'arguments' => [':newfieldinitial' => $specification['initial']],
+          'expression' => $expression,
+          'arguments' => $arguments,
         ];
       }
-      elseif (isset($specification['initial_from_field'])) {
+      elseif (isset($specification['initial'])) {
         // If we have a initial value, copy it over.
         $mapping[$field] = [
-          'expression' => $specification['initial_from_field'],
-          'arguments' => [],
+          'expression' => ':newfieldinitial',
+          'arguments' => [':newfieldinitial' => $specification['initial']],
         ];
       }
       else {
@@ -480,20 +502,27 @@ class Schema extends DatabaseSchema {
         $schema['fields'][$row->name] = [
           'type' => $type,
           'size' => $size,
-          'not null' => !empty($row->notnull),
+          'not null' => !empty($row->notnull) || $row->pk !== "0",
           'default' => trim($row->dflt_value, "'"),
         ];
         if ($length) {
           $schema['fields'][$row->name]['length'] = $length;
         }
+        // $row->pk contains a number that reflects the primary key order. We
+        // use that as the key and sort (by key) below to return the primary key
+        // in the same order that it is stored in.
         if ($row->pk) {
-          $schema['primary key'][] = $row->name;
+          $schema['primary key'][$row->pk] = $row->name;
         }
       }
       else {
         throw new \Exception("Unable to parse the column type " . $row->type);
       }
     }
+    ksort($schema['primary key']);
+    // Re-key the array because $row->pk starts counting at 1.
+    $schema['primary key'] = array_values($schema['primary key']);
+
     $indexes = [];
     $result = $this->connection->query('PRAGMA ' . $info['schema'] . '.index_list(' . $info['table'] . ')');
     foreach ($result as $row) {
@@ -529,9 +558,11 @@ class Schema extends DatabaseSchema {
 
     unset($new_schema['fields'][$field]);
 
-    // Handle possible primary key changes.
-    if (isset($new_schema['primary key']) && ($key = array_search($field, $new_schema['primary key'])) !== FALSE) {
-      unset($new_schema['primary key'][$key]);
+    // Drop the primary key if the field to drop is part of it. This is
+    // consistent with the behavior on PostgreSQL.
+    // @see \Drupal\Core\Database\Driver\mysql\Schema::dropField()
+    if (isset($new_schema['primary key']) && in_array($field, $new_schema['primary key'], TRUE)) {
+      unset($new_schema['primary key']);
     }
 
     // Handle possible index changes.
@@ -560,6 +591,9 @@ class Schema extends DatabaseSchema {
     if (($field != $field_new) && $this->fieldExists($table, $field_new)) {
       throw new SchemaObjectExistsException(t("Cannot rename field @table.@name to @name_new: target field already exists.", ['@table' => $table, '@name' => $field, '@name_new' => $field_new]));
     }
+    if (isset($keys_new['primary key']) && in_array($field_new, $keys_new['primary key'], TRUE)) {
+      $this->ensureNotNullPrimaryKey($keys_new['primary key'], [$field_new => $spec]);
+    }
 
     $old_schema = $this->introspectSchema($table);
     $new_schema = $old_schema;
@@ -611,8 +645,10 @@ class Schema extends DatabaseSchema {
       if (is_array($field)) {
         $field = &$field[0];
       }
-      if (isset($mapping[$field])) {
-        $field = $mapping[$field];
+
+      $mapped_field = array_search($field, $mapping, TRUE);
+      if ($mapped_field !== FALSE) {
+        $field = $mapped_field;
       }
     }
     return $key_definition;
@@ -707,6 +743,7 @@ class Schema extends DatabaseSchema {
     }
 
     $new_schema['primary key'] = $fields;
+    $this->ensureNotNullPrimaryKey($new_schema['primary key'], $new_schema['fields']);
     $this->alterTable($table, $old_schema, $new_schema);
   }
 
@@ -726,6 +763,17 @@ class Schema extends DatabaseSchema {
     return TRUE;
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  protected function findPrimaryKeyColumns($table) {
+    if (!$this->tableExists($table)) {
+      return FALSE;
+    }
+    $schema = $this->introspectSchema($table);
+    return $schema['primary key'];
+  }
+
   /**
    * {@inheritdoc}
    */