Verified Commit 6a0d80e4 authored by Dave Long's avatar Dave Long
Browse files

Issue #3399160 by mfb, smustgrave, bradjones1, Ghost of Drupal Past: Support MySQL GIPK mode

parent 3ae37397
Loading
Loading
Loading
Loading
Loading
+18 −1
Original line number Diff line number Diff line
@@ -2,12 +2,15 @@

namespace Drupal\mysql\Driver\Database\mysql;

use Drupal\Core\Database\DatabaseExceptionWrapper;
use Drupal\Core\Database\SchemaException;
use Drupal\Core\Database\SchemaObjectExistsException;
use Drupal\Core\Database\SchemaObjectDoesNotExistException;
use Drupal\Core\Database\Schema as DatabaseSchema;
use Drupal\Component\Utility\Unicode;

// cspell:ignore gipk

/**
 * @addtogroup schemaapi
 * @{
@@ -426,7 +429,21 @@ public function addField($table, $field, $spec, $keys_new = []) {

      $query .= ', ADD ' . implode(', ADD ', $keys_sql);
    }
    try {
      $this->connection->query($query);
    }
    catch (DatabaseExceptionWrapper $e) {
      // MySQL error number 4111 (ER_DROP_PK_COLUMN_TO_DROP_GIPK) indicates that
      // when dropping and adding a primary key, the generated invisible primary
      // key (GIPK) column must also be dropped.
      if (isset($e->getPrevious()->errorInfo[1]) && $e->getPrevious()->errorInfo[1] === 4111 && isset($keys_new['primary key']) && $this->indexExists($table, 'PRIMARY') && $this->findPrimaryKeyColumns($table) === ['my_row_id']) {
        $this->connection->query($query . ', DROP COLUMN [my_row_id]');
      }
      else {
        throw $e;
      }
    }

    if (isset($spec['initial_from_field'])) {
      if (isset($spec['initial'])) {
        $expression = 'COALESCE(' . $spec['initial_from_field'] . ', :default_initial_value)';
+29 −0
Original line number Diff line number Diff line
@@ -3,6 +3,7 @@
namespace Drupal\Tests\mysql\Kernel\mysql;

use Drupal\Component\Utility\Unicode;
use Drupal\Core\Database\DatabaseExceptionWrapper;
use Drupal\Core\Database\Exception\SchemaTableColumnSizeTooLargeException;
use Drupal\Core\Database\Exception\SchemaTableKeyTooLargeException;
use Drupal\Core\Database\SchemaException;
@@ -311,4 +312,32 @@ public function testSchemaTableColumnSizeTooLargeException(): void {
    ]);
  }

  /**
   * Tests adding a primary key when sql_generate_invisible_primary_key is on.
   */
  public function testGeneratedInvisiblePrimaryKey(): void {
    $is_maria = method_exists($this->connection, 'isMariaDb') && $this->connection->isMariaDb();
    if ($this->connection->databaseType() !== 'mysql' || $is_maria || version_compare($this->connection->version(), '8.0.30', '<')) {
      $this->markTestSkipped('This test only runs on MySQL 8.0.30 and above');
    }
    try {
      $this->connection->query("SET sql_generate_invisible_primary_key = 1;")->execute();
    }
    catch (DatabaseExceptionWrapper $e) {
      $this->markTestSkipped('This test requires the SESSION_VARIABLES_ADMIN privilege.');
    }
    $this->schema->createTable('test_primary_key', [
      'fields' => [
        'foo'  => [
          'type' => 'varchar',
          'length' => 1,
        ],
      ],
    ]);
    $this->schema->addField('test_primary_key', 'id', [
      'type' => 'serial',
      'not null' => TRUE,
    ], ['primary key' => ['id']]);
  }

}