Commit c5d5ed7d authored by Gábor Hojtsy's avatar Gábor Hojtsy
Browse files

Issue #3301036 by Gábor Hojtsy, Sergei Churilo, greg.1.anderson: Fix incorrect...

Issue #3301036 by Gábor Hojtsy, Sergei Churilo, greg.1.anderson: Fix incorrect MariaDB version reports when used in Drupal 8
parent f834f7c7
Loading
Loading
Loading
Loading
+17 −35
Original line number Diff line number Diff line
@@ -20,7 +20,7 @@ use Drupal\upgrade_status\CookieJar;
use Drupal\upgrade_status\DeprecationAnalyzer;
use Drupal\upgrade_status\ProjectCollector;
use Drupal\upgrade_status\ScanResultFormatter;
use Drupal\upgrade_status\Util\CorrectDbServerVersion;
use Drupal\upgrade_status\Util\DatabaseServerMetadataExtractor;
use Drupal\user\Entity\Role;
use GuzzleHttp\Cookie\SetCookie;
use Symfony\Component\DependencyInjection\ContainerInterface;
@@ -1007,58 +1007,40 @@ MARKUP
      ]
    ];

    // Check database version.
    $database_type = $this->database->databaseType();
    $version = $this->database->version();

    // If running on Drupal 8, the mysql driver might
    // mis-report the database version.
    if ($this->nextMajor == 9) {
      $versionFixer = new CorrectDbServerVersion($this->database);
      $version = $versionFixer->getCorrectedDbServerVersion($version);
    }
    $database_server_metadata_extractor = new DatabaseServerMetadataExtractor($this->database);
    $database_type = $database_server_metadata_extractor->getType();
    $version = $database_server_metadata_extractor->getVersion();

    // MariaDB databases report as MySQL. Detect MariaDB separately based on code from
    // https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Database%21Driver%21mysql%21Connection.php/function/Connection%3A%3AgetMariaDbVersionMatch/9.0.x
    // See also https://www.drupal.org/node/3119156 for test values.
    if ($database_type == 'mysql') {
      // MariaDB may prefix its version string with '5.5.5-', which should be
      // ignored.
      // @see https://github.com/MariaDB/server/blob/f6633bf058802ad7da8196d01fd19d75c53f7274/include/mysql_com.h#L42.
      $regex = '/^(?:5\\.5\\.5-)?(\\d+\\.\\d+\\.\\d+.*-mariadb.*)/i';
      preg_match($regex, $version, $matches);
      if (!empty($matches[1])) {
        $database_type_full_name = 'MariaDB';
        $version = $matches[1];
        $requirement = $this->t('When using MariaDB, minimum version is 10.3.7');
        if (version_compare($version, '10.3.7') >= 0) {
      $database_type_full_name = 'MySQL or Percona Server';
      $requirement = $this->t('When using MySQL/Percona, minimum version is 5.7.8');
      if (version_compare($version, '5.7.8') >= 0) {
        $class = 'no-known-error';
      }
        elseif (version_compare($version, '10.1.0') >= 0) {
      elseif (version_compare($version, '5.6.0') >= 0) {
        $class = 'known-warning';
          $requirement .= ' ' . $this->t('Alternatively, <a href=":driver">install the MariaDB 10.1 driver for Drupal 9</a> for now.', [':driver' => 'https://www.drupal.org/project/mysql56']);
        $requirement .= ' ' . $this->t('Alternatively, <a href=":driver">install the MySQL 5.6 driver for Drupal 9</a> for now.', [':driver' => 'https://www.drupal.org/project/mysql56']);
      }
      else {
        $status = FALSE;
        $class = 'known-error';
          $requirement .= ' ' . $this->t('Once updated to at least 10.1, you can also <a href=":driver">install the MariaDB 10.1 driver for Drupal 9</a> for now.', [':driver' => 'https://www.drupal.org/project/mysql56']);
        $requirement .= ' ' . $this->t('Once updated to at least 5.6, you can also <a href=":driver">install the MySQL 5.6 driver for Drupal 9</a> for now.', [':driver' => 'https://www.drupal.org/project/mysql56']);
      }
    }
      else {
        $database_type_full_name = 'MySQL or Percona Server';
        $requirement = $this->t('When using MySQL/Percona, minimum version is 5.7.8');
        if (version_compare($version, '5.7.8') >= 0) {
    elseif ($database_type == 'mariadb') {
      $database_type_full_name = 'MariaDB';
      $requirement = $this->t('When using MariaDB, minimum version is 10.3.7');
      if (version_compare($version, '10.3.7') >= 0) {
        $class = 'no-known-error';
      }
        elseif (version_compare($version, '5.6.0') >= 0) {
      elseif (version_compare($version, '10.1.0') >= 0) {
        $class = 'known-warning';
          $requirement .= ' ' . $this->t('Alternatively, <a href=":driver">install the MySQL 5.6 driver for Drupal 9</a> for now.', [':driver' => 'https://www.drupal.org/project/mysql56']);
        $requirement .= ' ' . $this->t('Alternatively, <a href=":driver">install the MariaDB 10.1 driver for Drupal 9</a> for now.', [':driver' => 'https://www.drupal.org/project/mysql56']);
      }
      else {
        $status = FALSE;
        $class = 'known-error';
          $requirement .= ' ' . $this->t('Once updated to at least 5.6, you can also <a href=":driver">install the MySQL 5.6 driver for Drupal 9</a> for now.', [':driver' => 'https://www.drupal.org/project/mysql56']);
        }
        $requirement .= ' ' . $this->t('Once updated to at least 10.1, you can also <a href=":driver">install the MariaDB 10.1 driver for Drupal 9</a> for now.', [':driver' => 'https://www.drupal.org/project/mysql56']);
      }
    }
    elseif ($database_type == 'pgsql') {
+40 −22
Original line number Diff line number Diff line
@@ -3,8 +3,9 @@
namespace Drupal\upgrade_status\Util;

use Drupal\Core\Database\Connection;
use Drupal\upgrade_status\ProjectCollector;

class CorrectDbServerVersion {
class DatabaseServerMetadataExtractor {

  /**
   * Database connection
@@ -14,26 +15,24 @@ class CorrectDbServerVersion {
  protected $database;

  /**
   * Cached database version (Used in Drupal 8.9.x only)
   * MySql database version.
   *
   * @var string
   */
  protected $databaseServerVersion;
  protected $mysqlVersion;

  /**
   * Constructs a Drupal\upgrade_status\Util\MariaDbServerVersion.
   *
   * @param \Drupal\Core\Database\Connection $connection
   *   The database connection
   * @param \Drupal\Core\Database\Connection $database
   *   The database connection.
   */
  public function __construct(
    Connection $database
  ) {
  public function __construct(Connection $database) {
    $this->database = $database;
  }

  /**
   * Returns corrected version of database.
   * Returns version of database.
   *
   * When running on MariaDb on Drupal 8.9.x, the version
   * from $database->version() is not reported correctly.
@@ -45,14 +44,28 @@ class CorrectDbServerVersion {
   * @see https://www.drupal.org/project/drupal/issues/3213482
   *
   * @return string
   *   Returns the MariaDb server version if applicable, or the passed-in
   *   Returns the MariaDb server version if applicable, or the default
   *   version if not.
   */
  public function getCorrectedDbServerVersion($version) {
  public function getVersion() {
    if ($this->isMariaDb()) {
      return $this->getMariaDbVersionMatch();
      return $this->getMariaDbVersion();
    }
    return $version;
    return $this->database->version();
  }

  /**
   * Returns type of database.
   *
   * @return string
   *   Returns specific to MariaDb type if applicable, or the default
   *   database server type if not.
   */
  public function getType() {
    if ($this->isMariaDb()) {
      return 'mariadb';
    }
    return $this->database->databaseType();
  }

  /**
@@ -62,7 +75,12 @@ class CorrectDbServerVersion {
   *   Returns TRUE if the distribution is MariaDB, or FALSE if not.
   */
  protected function isMariaDb(): bool {
    return (bool) $this->getMariaDbVersionMatch();
    if ($this->database->databaseType() !== 'mysql' || ProjectCollector::getDrupalCoreMajorVersion() !== 8) {
      return FALSE;
    }
    // If running on Drupal 8, the mysql driver might
    // mis-report the database version.
    return (bool) $this->getMariaDbVersion();
  }

  /**
@@ -71,26 +89,26 @@ class CorrectDbServerVersion {
   * @return string
   *   The MariaDB portion of the server version if present, or NULL if not.
   */
  protected function getMariaDbVersionMatch(): ?string {
  protected function getMariaDbVersion(): ?string {
    // MariaDB may prefix its version string with '5.5.5-', which should be
    // ignored.
    // @see https://github.com/MariaDB/server/blob/f6633bf058802ad7da8196d01fd19d75c53f7274/include/mysql_com.h#L42.
    $regex = '/^(?:5\.5\.5-)?(\d+\.\d+\.\d+.*-mariadb.*)/i';

    preg_match($regex, $this->getDatabaseServerVersion(), $matches);
    preg_match($regex, $this->getMysqlDbVersion(), $matches);
    return (empty($matches[1])) ? NULL : $matches[1];
  }

  /**
   * Gets the database server version.
   * Returns MySql database server version.
   *
   * @return string
   *   The database server version.
   *   MySql database server version.
   */
  protected function getDatabaseServerVersion(): string {
    if (!$this->databaseServerVersion) {
      $this->databaseServerVersion = $this->database->version();
  protected function getMysqlDbVersion(): string {
    if (!$this->mysqlVersion) {
      $this->mysqlVersion = $this->database->query('SELECT VERSION()')->fetchColumn();
    }
    return $this->databaseServerVersion;
    return $this->mysqlVersion;
  }
}