Commit 7dd526f4 authored by Cédric Anne's avatar Cédric Anne
Browse files

Enhance db:check command

- Move code to a dedicated and testable class;
- Check for indexes differences;
- Check for table options differences;
- Adapt checks to DB config, DB server and DB version;
- Add parameters to adapt checks depending on already ran migrations;
- Exit with an error code when differences are found;
- Permit do do a non strict check (do not take care or fields / index orders in table);
- Call the command after each migration on test suite;
- Add tests on most relevant cases.
parent 9b5ddeb0
......@@ -2,7 +2,7 @@
bin/console glpi:database:configure --config-dir=./tests --no-interaction --ansi --reconfigure --db-name=glpitest-9.5.3 --db-host=db --db-user=root --use-utf8mb4 --log-deprecation-warnings
# Force ROW_FORMAT_Dynamic to prevent tests MySQL 5.6 and MariaDB 10.1 databases
# Force ROW_FORMAT=DYNAMIC to prevent tests MySQL 5.6 and MariaDB 10.1 databases
# failure on indexes creation for varchar(255) fields.
## Result will depend on DB server/version, we just expect that command will not fail.
bin/console glpi:migration:dynamic_row_format --config-dir=./tests --ansi --no-interaction
......@@ -15,6 +15,8 @@ if [[ -n $(grep "Warning\|No migration needed." ~/migration.log) ]]; then echo "
## Second run should do nothing.
bin/console glpi:database:update --config-dir=./tests --ansi --no-interaction --allow-unstable | tee ~/migration.log
if [[ -z $(grep "No migration needed." ~/migration.log) ]]; then echo "bin/console glpi:database:update command FAILED" && exit 1; fi
## Check DB
bin/console glpi:database:check --config-dir=./tests --ansi --no-interaction --ignore-utf8mb4-migration
# Execute myisam_to_innodb migration
## First run should do nothing.
......@@ -33,3 +35,5 @@ if [[ -n $(grep "Warning\|No migration needed." ~/migration.log) ]]; then echo "
## Second run should do nothing.
bin/console glpi:migration:utf8mb4 --config-dir=./tests --ansi --no-interaction | tee ~/migration.log
if [[ -z $(grep "No migration needed." ~/migration.log) ]]; then echo "bin/console glpi:migration:utf8mb4 command FAILED" && exit 1; fi
# Check DB
bin/console glpi:database:check --config-dir=./tests --ansi --no-interaction
......@@ -9,6 +9,8 @@ if [[ -n $(grep "Warning\|No migration needed." ~/migration.log) ]]; then echo "
## Second run should do nothing.
bin/console glpi:database:update --config-dir=./tests --ansi --no-interaction --allow-unstable | tee ~/migration.log
if [[ -z $(grep "No migration needed." ~/migration.log) ]]; then echo "bin/console glpi:database:update command FAILED" && exit 1; fi
## Check DB
bin/console glpi:database:check --config-dir=./tests --ansi --no-interaction --ignore-innodb-migration --ignore-timestamps-migration --ignore-dynamic-row-format-migration --ignore-utf8mb4-migration
# Execute myisam_to_innodb migration
## First run should do the migration (with no warnings).
......@@ -17,6 +19,8 @@ if [[ -n $(grep "Warning\|No migration needed." ~/migration.log) ]]; then echo "
## Second run should do nothing.
bin/console glpi:migration:myisam_to_innodb --config-dir=./tests --ansi --no-interaction | tee ~/migration.log
if [[ -z $(grep "No migration needed." ~/migration.log) ]]; then echo "bin/console glpi:migration:myisam_to_innodb command FAILED" && exit 1; fi
## Check DB
bin/console glpi:database:check --config-dir=./tests --ansi --no-interaction --ignore-timestamps-migration --ignore-dynamic-row-format-migration --ignore-utf8mb4-migration
# Execute timestamps migration
## First run should do the migration (with no warnings).
......@@ -25,10 +29,14 @@ if [[ -n $(grep "Warning\|No migration needed." ~/migration.log) ]]; then echo "
## Second run should do nothing.
bin/console glpi:migration:timestamps --config-dir=./tests --ansi --no-interaction | tee ~/migration.log
if [[ -z $(grep "No migration needed." ~/migration.log) ]]; then echo "bin/console glpi:migration:timestamps command FAILED" && exit 1; fi
## Check DB
bin/console glpi:database:check --config-dir=./tests --ansi --no-interaction --ignore-dynamic-row-format-migration --ignore-utf8mb4-migration
# Execute dynamic_row_format migration
## Result will depend on DB server/version, we just expect that command will not fail.
bin/console glpi:migration:dynamic_row_format --config-dir=./tests --ansi --no-interaction
## Check DB
bin/console glpi:database:check --config-dir=./tests --ansi --no-interaction --ignore-utf8mb4-migration
# Execute utf8mb4 migration
## First run should do the migration (with no warnings).
......@@ -37,3 +45,5 @@ if [[ -n $(grep "Warning\|No migration needed." ~/migration.log) ]]; then echo "
## Second run should do nothing.
bin/console glpi:migration:utf8mb4 --config-dir=./tests --ansi --no-interaction | tee ~/migration.log
if [[ -z $(grep "No migration needed." ~/migration.log) ]]; then echo "bin/console glpi:migration:utf8mb4 command FAILED" && exit 1; fi
## Check DB
bin/console glpi:database:check --config-dir=./tests --ansi --no-interaction
......@@ -215,15 +215,6 @@ jobs:
if: env.skip != 'true'
run: |
docker exec app vendor/bin/parallel-lint --exclude ./files/ --exclude ./marketplace/ --exclude ./plugins/ --exclude ./tools/vendor/ --exclude ./vendor/ .
- name: "Install DB tests"
if: env.skip != 'true'
run: |
docker exec app bin/console glpi:database:install --config-dir=./tests --ansi --no-interaction --reconfigure --db-name=glpi --db-host=db --db-user=root --log-deprecation-warnings | tee install.log
if [[ -n $(grep "Warning" install.log) ]]; then echo "glpi:database:install command FAILED" && exit 1; fi
docker exec app bin/console glpi:database:check --config-dir=./tests --ansi --no-interaction | tee diff.log
if [[ -z $(grep "Database schema is OK." diff.log) ]]; then echo "glpi:database:check command FAILED" && exit 1; fi
docker exec app bin/console glpi:database:update --config-dir=./tests --ansi --no-interaction | tee migration.log
if [[ -z $(grep "No migration needed." migration.log) ]]; then echo "glpi:database:update command FAILED" && exit 1; fi
- name: "Update DB tests (from 0.80, not using utf8mb4)"
if: env.skip != 'true'
run: |
......@@ -232,11 +223,14 @@ jobs:
if: env.skip != 'true'
run: |
docker exec app .github/actions/test_update_from_9.5.sh
- name: "Database tests"
- name: "Install DB tests"
if: env.skip != 'true'
run: |
docker exec app bin/console glpi:database:configure --config-dir=./tests --ansi --no-interaction --reconfigure --db-name=glpi --db-host=db --db-user=root --use-utf8mb4 --log-deprecation-warnings
docker exec app vendor/bin/atoum -p 'php -d memory_limit=512M' --debug --force-terminal --use-dot-report --bootstrap-file tests/bootstrap.php --no-code-coverage --fail-if-skipped-methods --max-children-number 1 -d tests/database
docker exec app bin/console glpi:database:install --config-dir=./tests --ansi --no-interaction --reconfigure --db-name=glpi --db-host=db --db-user=root --log-deprecation-warnings | tee install.log
if [[ -n $(grep "Warning" install.log) ]]; then echo "glpi:database:install command FAILED" && exit 1; fi
docker exec app bin/console glpi:database:check --config-dir=./tests --ansi --no-interaction --strict
docker exec app bin/console glpi:database:update --config-dir=./tests --ansi --no-interaction | tee migration.log
if [[ -z $(grep "No migration needed." migration.log) ]]; then echo "glpi:database:update command FAILED" && exit 1; fi
- name: "Unit tests"
if: env.skip != 'true'
run: |
......
......@@ -26,6 +26,7 @@ The present file will list all changes made to the project; according to the
#### Deprecated
- Usage of `GLPI_FORCE_EMPTY_SQL_MODE` constant
- Usage of `CommonDBTM::notificationqueueonaction` property
- `DBmysql::getTableSchema()`
- `Calendar::duplicate()`
- `CommonDBTM::clone()`
- `CommonDBTM::prepareInputForClone()`
......
......@@ -37,8 +37,9 @@ if (!defined('GLPI_ROOT')) {
}
use Glpi\Console\AbstractCommand;
use SebastianBergmann\Diff\Differ;
use Glpi\System\Diagnostic\DatabaseChecker;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
class CheckCommand extends AbstractCommand {
......@@ -50,17 +51,66 @@ class CheckCommand extends AbstractCommand {
*/
const ERROR_UNABLE_TO_READ_EMPTYSQL = 1;
/**
* Error code returned differences were found.
*
* @var integer
*/
const ERROR_FOUND_DIFFERENCES = 2;
protected function configure() {
parent::configure();
$this->setName('glpi:database:check');
$this->setAliases(['db:check']);
$this->setDescription(__('Check for schema differences between current database and installation file.'));
$this->addOption(
'strict',
null,
InputOption::VALUE_NONE,
__('Strict comparison of definitions')
);
$this->addOption(
'ignore-innodb-migration',
null,
InputOption::VALUE_NONE,
__('Do not check tokens related to migration from "MyISAM" to "InnoDB".')
);
$this->addOption(
'ignore-timestamps-migration',
null,
InputOption::VALUE_NONE,
__('Do not check tokens related to migration from "datetime" to "timestamp".')
);
$this->addOption(
'ignore-utf8mb4-migration',
null,
InputOption::VALUE_NONE,
__('Do not check tokens related to migration from "utf8" to "utf8mb4".')
);
$this->addOption(
'ignore-dynamic-row-format-migration',
null,
InputOption::VALUE_NONE,
__('Do not check tokens related to "DYNAMIC" row format migration.')
);
}
protected function execute(InputInterface $input, OutputInterface $output) {
$differ = new Differ();
$checker = new DatabaseChecker(
$this->db,
$input->getOption('strict'),
$input->getOption('ignore-innodb-migration'),
$input->getOption('ignore-timestamps-migration'),
$input->getOption('ignore-utf8mb4-migration'),
$input->getOption('ignore-dynamic-row-format-migration')
);
if (false === ($empty_file = realpath(GLPI_ROOT . '/install/mysql/glpi-empty.sql'))
|| false === ($empty_sql = file_get_contents($empty_file))) {
......@@ -87,27 +137,25 @@ class CheckCommand extends AbstractCommand {
OutputInterface::VERBOSITY_VERY_VERBOSE
);
$base_table_struct = $this->db->getTableSchema($table_name, $table_schema);
$existing_table_struct = $this->db->getTableSchema($table_name);
if ($checker->hasDifferences($table_name, $table_schema)) {
$diff = $checker->getDiff($table_name, $table_schema);
if ($existing_table_struct['schema'] != $base_table_struct['schema']) {
$has_differences = true;
$message = sprintf(__('Table schema differs for table "%s".'), $table_name);
$output->writeln(
'<info>' . $message . '</info>',
OutputInterface::VERBOSITY_QUIET
);
$output->write(
$differ->diff($base_table_struct['schema'], $existing_table_struct['schema'])
);
$output->write($diff);
}
}
if (!$has_differences) {
$output->writeln('<info>' . __('Database schema is OK.') . '</info>');
return 0;
if ($has_differences) {
return self::ERROR_FOUND_DIFFERENCES;
}
$output->writeln('<info>' . __('Database schema is OK.') . '</info>');
return 0; // Success
}
}
......@@ -89,7 +89,7 @@ class DynamicRowFormatCommand extends AbstractCommand {
// Check that DB configuration is compatible
$version = preg_replace('/^((\d+\.?)+).*$/', '$1', $this->db->getVersion());
if (version_compare($version, '5.7', '<')) {
// On MySQL 5.6, "ROW_FORMAT = Dynamic" fallbacks to "ROW_FORMAT = Compact"
// On MySQL 5.6, "ROW_FORMAT = DYNAMIC" fallbacks to "ROW_FORMAT = COMPACT"
// if "innodb_file_format" is not set to "Barracuda".
// This variable has been removed in MySQL 8.0 and in MariaDB 10.3.
$query = 'SELECT @@GLOBAL.' . $this->db->quoteName('innodb_file_format as innodb_file_format');
......@@ -128,7 +128,7 @@ class DynamicRowFormatCommand extends AbstractCommand {
$table_iterator = $this->db->listTables(
'glpi\_%',
[
'row_format' => ['Compact', 'Redundant'],
'row_format' => ['COMPACT', 'REDUNDANT'],
]
);
......@@ -139,7 +139,7 @@ class DynamicRowFormatCommand extends AbstractCommand {
$this->output->writeln(
sprintf(
'<info>' . __('Found %s table(s) requiring a migration to "ROW_FORMAT=Dynamic".') . '</info>',
'<info>' . __('Found %s table(s) requiring a migration to "ROW_FORMAT=DYNAMIC".') . '</info>',
$table_iterator->count()
)
);
......
......@@ -120,7 +120,7 @@ class Utf8mb4Command extends AbstractCommand {
}
// Check that all tables are using the "Dynamic" row format
if ($this->db->listTables('glpi\_%', ['row_format' => ['Compact', 'Redundant']])->count() > 0) {
if ($this->db->listTables('glpi\_%', ['row_format' => ['COMPACT', 'REDUNDANT']])->count() > 0) {
$msg = sprintf(
__('%d tables are still using Compact or Redundant row format. Run "php bin/console glpi:migration:dynamic_row_format" to fix this.'),
$myisam_count
......
......@@ -1335,8 +1335,12 @@ class DBmysql {
* @param string|null $structure Raw table structure
*
* @return array
*
* @deprecated x.x.x
*/
public function getTableSchema($table, $structure = null) {
Toolbox::deprecated();
if ($structure === null) {
$structure = $this->query("SHOW CREATE TABLE `$table`")->fetch_row();
$structure = $structure[1];
......
<?php
/**
* ---------------------------------------------------------------------
* GLPI - Gestionnaire Libre de Parc Informatique
* Copyright (C) 2015-2021 Teclib' and contributors.
*
* http://glpi-project.org
*
* based on GLPI - Gestionnaire Libre de Parc Informatique
* Copyright (C) 2003-2014 by the INDEPNET Development Team.
*
* ---------------------------------------------------------------------
*
* LICENSE
*
* This file is part of GLPI.
*
* GLPI is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* GLPI is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GLPI. If not, see <http://www.gnu.org/licenses/>.
* ---------------------------------------------------------------------
*/
namespace Glpi\System\Diagnostic;
if (!defined('GLPI_ROOT')) {
die("Sorry. You can't access this file directly");
}
use DBmysql;
use SebastianBergmann\Diff\Differ;
/**
* @since x.x.x
*/
class DatabaseChecker {
/**
* DB instance.
*
* @var DBmysql
*/
protected $db;
/**
* Do not check tokens related to "DYNAMIC" row format migration.
*
* @var bool
*/
protected $ignore_dynamic_row_format_migration;
/**
* Do not check tokens related to migration from "MyISAM" to "InnoDB".
*
* @var bool
*/
protected $ignore_innodb_migration;
/**
* Do not check tokens related to migration from "datetime" to "timestamp".
*
* @var bool
*/
protected $ignore_timestamps_migration;
/**
* Do not check tokens related to migration from "utf8" to "utf8mb4".
*
* @var bool
*/
protected $ignore_utf8mb4_migration;
/**
* Ignore differences that has no effect on application (columns and keys order for instance).
*
* @var bool
*/
protected $strict;
/**
* Local cache for normalized SQL.
*
* @var array
*/
private $normalized = [];
/**
* @param DBmysql $db DB instance.
* @param bool $strict Ignore differences that has no effect on application (columns and keys order for instance).
* @param bool $ignore_innodb_migration Do not check tokens related to migration from "MyISAM" to "InnoDB".
* @param bool $ignore_timestamps_migration Do not check tokens related to migration from "datetime" to "timestamp".
* @param bool $ignore_utf8mb4_migration Do not check tokens related to migration from "utf8" to "utf8mb4".
* @param bool $ignore_dynamic_row_format_migration Do not check tokens related to "DYNAMIC" row format migration.
*/
public function __construct(
DBmysql $db,
bool $strict = true,
bool $ignore_innodb_migration = false,
bool $ignore_timestamps_migration = false,
bool $ignore_utf8mb4_migration = false,
bool $ignore_dynamic_row_format_migration = false
) {
$this->db = $db;
$this->strict = $strict;
$this->ignore_dynamic_row_format_migration = $ignore_dynamic_row_format_migration;
$this->ignore_innodb_migration = $ignore_innodb_migration;
$this->ignore_timestamps_migration = $ignore_timestamps_migration;
$this->ignore_utf8mb4_migration = $ignore_utf8mb4_migration;
}
/**
* Check is there is differences between effective table structure and proper structure contained in "CREATE TABLE" sql query.
*
* @param string $table_name
* @param string $proper_create_table_sql
*
* @return bool
*/
public function hasDifferences(string $table_name, string $proper_create_table_sql): bool {
$effective_create_table_sql = $this->getEffectiveCreateTableSql($table_name);
$proper_create_table_sql = $this->getNomalizedSql($proper_create_table_sql);
$effective_create_table_sql = $this->getNomalizedSql($effective_create_table_sql);
return $proper_create_table_sql !== $effective_create_table_sql;
}
/**
* Get diff between effective table structure and proper structure contained in "CREATE TABLE" sql query.
*
* @param string $table
* @param string $proper_create_table_sql
*
* @return string
*/
public function getDiff(string $table_name, string $proper_create_table_sql): string {
$effective_create_table_sql = $this->getEffectiveCreateTableSql($table_name);
$proper_create_table_sql = $this->getNomalizedSql($proper_create_table_sql);
$effective_create_table_sql = $this->getNomalizedSql($effective_create_table_sql);
if ($proper_create_table_sql === $effective_create_table_sql) {
return '';
}
$differ = new Differ();
return $differ->diff(
$this->getNomalizedSql($proper_create_table_sql),
$this->getNomalizedSql($effective_create_table_sql)
);
}
/**
* Returns "CREATE TABLE" SQL returned by DB itself.
*
* @param string $table_name
*
* @return string
*/
protected function getEffectiveCreateTableSql(string $table_name): string {
if (($create_table_res = $this->db->query('SHOW CREATE TABLE ' . $this->db->quoteName($table_name))) === false) {
if ($this->db->errno() == 1146) {
return ''; // Table does not exists, effective create table is empty (will output full proper query as diff).
}
throw new \Exception(sprintf('Unable to get table "%s" structure', $table_name));
}
return $create_table_res->fetch_assoc()['Create Table'];
}
/**
* Returns normalized SQL.
* Normalization replace/remove tokens that can reveal differences we do not want to see.
*
* @param string $create_table_sql
*
* @return string
*/
protected function getNomalizedSql(string $create_table_sql): string {
$cache_key = md5($create_table_sql);
if (array_key_exists($cache_key, $this->normalized)) {
return $this->normalized[$cache_key];
}
// Extract informations
$matches = [];
if (!preg_match('/^CREATE TABLE `(?<table>\w+)` \((?<structure>.+)\)(?<properties>[^\)]*)$/is', $create_table_sql, $matches)) {
return $create_table_sql;// Unable to normalize
}
$table_name = $matches['table'];
$structure_sql = $matches['structure'];
$properties_sql = $matches['properties'];
$columns_matches = [];
$indexes_matches = [];
$properties_matches = [];
if (!preg_match_all('/^\s*(?<column>`\w+` .+?),?$/im', $structure_sql, $columns_matches)
|| !preg_match_all('/^\s*(?<index>(CONSTRAINT|(UNIQUE |PRIMARY )?KEY) .+?),?$/im', $structure_sql, $indexes_matches)
|| !preg_match_all('/\s+((?<property>[^=]+[^\s])\s*=\s*(?<value>(\w+|\'(\\.|[^"])+\')))/i', $properties_sql, $properties_matches)) {
return $create_table_sql;// Unable to normalize
}
$columns = $columns_matches['column'];
$indexes = $indexes_matches['index'];
$properties = array_combine($properties_matches['property'], $properties_matches['value']);
$db_version_string = $this->db->getVersion();
$db_server = preg_match('/-MariaDB/', $db_version_string) ? 'MariaDB': 'MySQL';
$db_version = preg_replace('/^((\d+\.?)+).*$/', '$1', $db_version_string);
// Normalize columns definitions
if (!$this->strict) {
sort($columns);
}
$column_replacements = [
// Remove comments
'/ COMMENT \'.+\'/i' => '',
// Remove integer display width
'/( (tiny|small|medium|big)?int)\(\d+\)/i' => '$1',
];
if ($db_server === 'MariaDB' && version_compare($db_version, '10.2', '>=')) {
// Add surrounding quotes on default numeric values (MySQL has quotes while MariaDB 10.2+ has not)
$column_replacements['/(DEFAULT) ([-|+]?\d+(\.\d+)?)/i'] = '$1 \'$2\'';
// Replace function current_timestamp() by CURRENT_TIMESTAMP (MySQL uses constant while MariaDB 10.2+ uses function)
$column_replacements['/current_timestamp\(\)/i'] = 'CURRENT_TIMESTAMP';
// Remove DEFAULT NULL on text fields (MySQL has not while MariaDB 10.2+ has)
$column_replacements['/( (medium|long)?(blob|text)[^,]*) DEFAULT NULL/i'] = '$1';
}
if ($this->ignore_timestamps_migration) {
$column_replacements['/ timestamp( NULL)?/i'] = ' datetime';
}
if ($this->ignore_utf8mb4_migration) {
$column_replacements['/( CHARACTER SET (utf8|utf8mb4))? COLLATE (utf8_unicode_ci|utf8mb4_unicode_ci)/i'] = '';
}
if ($this->db->use_utf8mb4) {
// Remove default charset / collate
$column_replacements['/( CHARACTER SET utf8mb4)? COLLATE utf8mb4_unicode_ci/i'] = '';
// text were replaced by mediumtext during utf8mb4 migration
$column_replacements['/mediumtext/i'] = 'text';
} else {
// Remove default charset / collate
$column_replacements['/( CHARACTER SET utf8)? COLLATE utf8_unicode_ci/i'] = '';
}
$columns = preg_replace(array_keys($column_replacements), array_values($column_replacements), $columns);
// Normalize indexes definitions
if (!$this->strict) {
sort($indexes);
}
// Normalize properties
unset($properties['AUTO_INCREMENT']);
unset($properties['COMMENT']);
if ($this->ignore_dynamic_row_format_migration) {
unset($properties['ROW_FORMAT']);
}
if (!$this->strict && ($properties['ROW_FORMAT'] ?? '') === 'DYNAMIC'
&& (
($db_server === 'MySQL' && version_compare($db_version, '5.7', '>='))
|| ($db_server === 'MariaDB' && version_compare($db_version, '10.2', '>='))
)) {
// MySQL 5.7+ and MariaDB 10.2+ does not ouput ROW_FORMAT when ROW_FORMAT has not been specified in creation query
// and so uses default value.
unset($properties['ROW_FORMAT']);
}
if ($this->ignore_innodb_migration) {
unset($properties['ENGINE']);
}
if ($this->ignore_utf8mb4_migration) {
// Remove non specific character set / collate
if (in_array($properties['DEFAULT CHARSET'] ?? '', ['utf8', 'utf8mb4'])) {
unset($properties['DEFAULT CHARSET']);
}
if (in_array($properties['COLLATE'] ?? '', ['utf8_unicode_ci', 'utf8mb4_unicode_ci'])) {
unset($properties['COLLATE']);
}
}
ksort($properties);
// Rebuild SQL
$normalized_sql = "CREATE TABLE `{$table_name}` (\n";
$definitions = array_merge($columns, $indexes);
foreach ($definitions as $i => $definition) {
$normalized_sql .= ' ' . $definition . ($i < count($definitions) -1 ? ',' : '') . "\n";
}
$normalized_sql .= ')';
foreach ($properties as $key => $value) {
$normalized_sql .= ' ' . trim($key) . '=' . trim($value);
}
// Store in local cache
$this->normalized[$cache_key] = $normalized_sql;
return $normalized_sql;
}
}
......@@ -58,7 +58,7 @@ class DbConfiguration extends AbstractRequirement {
protected function check() {
$version = preg_replace('/^((\d+\.?)+).*$/', '$1', $this->db->getVersion());
// On MySQL 5.6, "ROW_FORMAT = Dynamic" fallbacks to "ROW_FORMAT = Compact"
// On MySQL 5.6, "ROW_FORMAT = DYNAMIC" fallbacks to "ROW_FORMAT = COMPACT"
// if "innodb_file_format" is not set to "Barracuda".
// This variable has been removed in MySQL 8.0 and in MariaDB 10.3.
$check_file_format = version_compare($version, '5.7', '<');
......
......@@ -47,14 +47,13 @@ function update95toXX() {
$migration->setVersion('x.x.x');
$update_scripts = [
'comment_fields',
'date_fields_defaults',
'devicebattery',
'documents',
'domains',
'native_inventory',
'recurrentchange',
'reservationitem',
'schema_fixes',
'softwares',
'uuids',
];
......