From 5d6f465615b1aba0a59c5b2b25178e653e685a20 Mon Sep 17 00:00:00 2001 From: Sami Mazouz Date: Fri, 29 Nov 2024 17:25:22 +0100 Subject: [PATCH] feat: separate mariadb driver --- .github/workflows/REUSABLE_backend.yml | 2 +- .../src/Api/Controller/ShowStatisticsData.php | 2 +- ...11_120604_change_posts_table_to_innodb.php | 5 ++-- ...1_convert_preferences_to_json_in_users.php | 21 +++++++++-------- ..._convert_data_to_json_in_notifications.php | 21 +++++++++-------- .../src/Database/DatabaseServiceProvider.php | 3 ++- .../src/Discussion/Search/FulltextFilter.php | 2 +- .../Foundation/ApplicationInfoProvider.php | 3 ++- .../src/Install/Console/UserDataProvider.php | 6 ++--- .../Install/Controller/InstallController.php | 2 +- framework/core/src/Install/DatabaseConfig.php | 12 +++++----- .../src/Install/Steps/ConnectToDatabase.php | 23 +++++++++++++++++++ .../core/src/Post/Filter/FulltextFilter.php | 2 +- framework/core/views/install/install.php | 3 ++- .../src/integration/Setup/SetupScript.php | 2 +- 15 files changed, 71 insertions(+), 38 deletions(-) diff --git a/.github/workflows/REUSABLE_backend.yml b/.github/workflows/REUSABLE_backend.yml index 54c0475a19..aeabd922a6 100644 --- a/.github/workflows/REUSABLE_backend.yml +++ b/.github/workflows/REUSABLE_backend.yml @@ -94,7 +94,7 @@ jobs: driver: mysql - service: mariadb db: MariaDB - driver: mysql + driver: mariadb - service: 'mysql:8.1.0' db: MySQL 8.1 driver: mysql diff --git a/extensions/statistics/src/Api/Controller/ShowStatisticsData.php b/extensions/statistics/src/Api/Controller/ShowStatisticsData.php index e90d6c0abe..9cff1f0e58 100644 --- a/extensions/statistics/src/Api/Controller/ShowStatisticsData.php +++ b/extensions/statistics/src/Api/Controller/ShowStatisticsData.php @@ -142,7 +142,7 @@ private function getTimedCounts(Builder $query, string $column, ?DateTime $start $dbFormattedDatetime = match ($query->getConnection()->getDriverName()) { 'sqlite' => "strftime($format, $column)", 'pgsql' => "TO_CHAR($column, $format)", - 'mysql' => "DATE_FORMAT($column, $format)", + 'mysql', 'mariadb' => "DATE_FORMAT($column, $format)", default => throw new Exception('Unsupported database driver'), }; diff --git a/framework/core/migrations/2018_01_11_120604_change_posts_table_to_innodb.php b/framework/core/migrations/2018_01_11_120604_change_posts_table_to_innodb.php index 2cf3cadfa4..fee5c7b86f 100644 --- a/framework/core/migrations/2018_01_11_120604_change_posts_table_to_innodb.php +++ b/framework/core/migrations/2018_01_11_120604_change_posts_table_to_innodb.php @@ -7,13 +7,14 @@ * LICENSE file that was distributed with this source code. */ +use Illuminate\Database\MySqlConnection; use Illuminate\Database\Schema\Builder; return [ 'up' => function (Builder $schema) { $connection = $schema->getConnection(); - if ($connection->getDriverName() === 'mysql') { + if ($connection->getDriverName() instanceof MySqlConnection) { $prefix = $connection->getTablePrefix(); $connection->statement('ALTER TABLE '.$prefix.'posts ENGINE = InnoDB'); } @@ -22,7 +23,7 @@ 'down' => function (Builder $schema) { $connection = $schema->getConnection(); - if ($connection->getDriverName() === 'mysql') { + if ($connection->getDriverName() instanceof MySqlConnection) { $prefix = $connection->getTablePrefix(); $connection->statement('ALTER TABLE '.$prefix.'posts ENGINE = MyISAM'); } diff --git a/framework/core/migrations/2024_05_05_000001_convert_preferences_to_json_in_users.php b/framework/core/migrations/2024_05_05_000001_convert_preferences_to_json_in_users.php index 5181c8558c..5abdaa4a72 100644 --- a/framework/core/migrations/2024_05_05_000001_convert_preferences_to_json_in_users.php +++ b/framework/core/migrations/2024_05_05_000001_convert_preferences_to_json_in_users.php @@ -8,6 +8,7 @@ */ use Illuminate\Database\MariaDbConnection; +use Illuminate\Database\MySqlConnection; use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Schema\Builder; @@ -26,14 +27,16 @@ $table->json('preferences_json')->nullable(); }); - if ($connection instanceof MariaDbConnection) { - $connection->table('users')->update([ - 'preferences_json' => $connection->raw("IF(JSON_VALID(CONVERT($preferences USING utf8mb4)), CONVERT($preferences USING utf8mb4), NULL)"), - ]); - } elseif ($driver === 'mysql') { - $connection->table('users')->update([ - 'preferences_json' => $connection->raw("CAST(CONVERT($preferences USING utf8mb4) AS JSON)"), - ]); + if ($connection instanceof MySqlConnection) { + if ($connection->isMaria()) { + $connection->table('users')->update([ + 'preferences_json' => $connection->raw("IF(JSON_VALID(CONVERT($preferences USING utf8mb4)), CONVERT($preferences USING utf8mb4), NULL)"), + ]); + } else { + $connection->table('users')->update([ + 'preferences_json' => $connection->raw("CAST(CONVERT($preferences USING utf8mb4) AS JSON)"), + ]); + } } $schema->table('users', function (Blueprint $table) { @@ -60,7 +63,7 @@ $table->binary('preferences_binary')->nullable(); }); - if ($driver === 'mysql') { + if ($connection instanceof MySqlConnection) { $connection->table('users')->update([ 'preferences_binary' => $connection->raw($preferences), ]); diff --git a/framework/core/migrations/2024_05_07_000001_convert_data_to_json_in_notifications.php b/framework/core/migrations/2024_05_07_000001_convert_data_to_json_in_notifications.php index 3ecc2842ab..0d3fb466b4 100644 --- a/framework/core/migrations/2024_05_07_000001_convert_data_to_json_in_notifications.php +++ b/framework/core/migrations/2024_05_07_000001_convert_data_to_json_in_notifications.php @@ -8,6 +8,7 @@ */ use Illuminate\Database\MariaDbConnection; +use Illuminate\Database\MySqlConnection; use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Schema\Builder; @@ -25,14 +26,16 @@ $table->json('data_json')->nullable(); }); - if ($connection instanceof MariaDbConnection) { - $connection->table('notifications')->update([ - 'data_json' => $connection->raw('IF(JSON_VALID(CONVERT(data USING utf8mb4)), CONVERT(data USING utf8mb4), NULL)'), - ]); - } elseif ($driver === 'mysql') { - $connection->table('notifications')->update([ - 'data_json' => $connection->raw('CAST(CONVERT(data USING utf8mb4) AS JSON)'), - ]); + if ($connection instanceof MySqlConnection) { + if ($connection->isMaria()) { + $connection->table('notifications')->update([ + 'data_json' => $connection->raw('IF(JSON_VALID(CONVERT(data USING utf8mb4)), CONVERT(data USING utf8mb4), NULL)'), + ]); + } else { + $connection->table('notifications')->update([ + 'data_json' => $connection->raw('CAST(CONVERT(data USING utf8mb4) AS JSON)'), + ]); + } } $schema->table('notifications', function (Blueprint $table) { @@ -58,7 +61,7 @@ $table->binary('data_binary')->nullable(); }); - if ($driver === 'mysql') { + if ($connection instanceof MySqlConnection) { $connection->table('notifications')->update([ 'data_binary' => $connection->raw('data'), ]); diff --git a/framework/core/src/Database/DatabaseServiceProvider.php b/framework/core/src/Database/DatabaseServiceProvider.php index ce43aa623d..572ae09cb5 100644 --- a/framework/core/src/Database/DatabaseServiceProvider.php +++ b/framework/core/src/Database/DatabaseServiceProvider.php @@ -37,7 +37,7 @@ public function register(): void $config = $container['flarum']->config('database'); - if ($config['driver'] === 'mysql') { + if (in_array($config['driver'], ['mysql', 'mariadb'])) { $config['engine'] = 'InnoDB'; } elseif ($config['driver'] === 'sqlite' && ! file_exists($config['database'])) { $config['database'] = $container->make(Paths::class)->base.'/'.$config['database']; @@ -85,6 +85,7 @@ protected function registerBuilderMacros(): void { $drivers = [ 'mysql' => 'MySql', + 'mariadb' => 'MariaDb', 'pgsql' => 'PgSql', 'sqlite' => 'Sqlite', ]; diff --git a/framework/core/src/Discussion/Search/FulltextFilter.php b/framework/core/src/Discussion/Search/FulltextFilter.php index 44d2489c51..0a890ca836 100644 --- a/framework/core/src/Discussion/Search/FulltextFilter.php +++ b/framework/core/src/Discussion/Search/FulltextFilter.php @@ -33,7 +33,7 @@ public function __construct( public function search(SearchState $state, string $value): void { match ($state->getQuery()->getConnection()->getDriverName()) { - 'mysql' => $this->mysql($state, $value), + 'mysql', 'mariadb' => $this->mysql($state, $value), 'pgsql' => $this->pgsql($state, $value), 'sqlite' => $this->sqlite($state, $value), default => throw new RuntimeException('Unsupported database driver: '.$state->getQuery()->getConnection()->getDriverName()), diff --git a/framework/core/src/Foundation/ApplicationInfoProvider.php b/framework/core/src/Foundation/ApplicationInfoProvider.php index 075bb3ff95..7bdbec5085 100644 --- a/framework/core/src/Foundation/ApplicationInfoProvider.php +++ b/framework/core/src/Foundation/ApplicationInfoProvider.php @@ -71,7 +71,7 @@ public function identifyQueueDriver(): string public function identifyDatabaseVersion(): string { return match ($this->config['database.driver']) { - 'mysql', 'pgsql' => $this->db->selectOne('select version() as version')->version, + 'mysql', 'mariadb', 'pgsql' => $this->db->selectOne('select version() as version')->version, 'sqlite' => $this->db->selectOne('select sqlite_version() as version')->version, default => 'Unknown', }; @@ -81,6 +81,7 @@ public function identifyDatabaseDriver(): string { return match ($this->config['database.driver']) { 'mysql' => 'MySQL', + 'mariadb' => 'MariaDB', 'pgsql' => 'PostgreSQL', 'sqlite' => 'SQLite', default => $this->config['database.driver'], diff --git a/framework/core/src/Install/Console/UserDataProvider.php b/framework/core/src/Install/Console/UserDataProvider.php index 2d25f2bd08..60a71947a0 100644 --- a/framework/core/src/Install/Console/UserDataProvider.php +++ b/framework/core/src/Install/Console/UserDataProvider.php @@ -43,14 +43,14 @@ public function configure(Installation $installation): Installation private function getDatabaseConfiguration(): DatabaseConfig { - $driver = $this->ask('Database driver (mysql, sqlite, pgsql) (Default: mysql):', 'mysql'); + $driver = $this->ask('Database driver (mysql, mariadb, sqlite, pgsql) (Default: mysql):', 'mysql'); $port = match ($driver) { - 'mysql' => 3306, + 'mysql', 'mariadb' => 3306, 'pgsql' => 5432, default => 0, }; - if (in_array($driver, ['mysql', 'pgsql'])) { + if (in_array($driver, ['mysql', 'mariadb', 'pgsql'])) { $host = $this->ask('Database host (required):', required: true); if (Str::contains($host, ':')) { diff --git a/framework/core/src/Install/Controller/InstallController.php b/framework/core/src/Install/Controller/InstallController.php index fee31cd69c..484c9e3d36 100644 --- a/framework/core/src/Install/Controller/InstallController.php +++ b/framework/core/src/Install/Controller/InstallController.php @@ -79,7 +79,7 @@ private function makeDatabaseConfig(array $input): DatabaseConfig $driver = Arr::get($input, 'dbDriver'); $host = Arr::get($input, 'dbHost'); $port = match ($driver) { - 'mysql' => 3306, + 'mysql', 'mariadb' => 3306, 'pgsql' => 5432, default => 0, }; diff --git a/framework/core/src/Install/DatabaseConfig.php b/framework/core/src/Install/DatabaseConfig.php index f093f76f2c..325bff6aad 100644 --- a/framework/core/src/Install/DatabaseConfig.php +++ b/framework/core/src/Install/DatabaseConfig.php @@ -42,15 +42,15 @@ private function validate(): void throw new ValidationFailed('Please specify a database driver.'); } - if (! in_array($this->driver, ['mysql', 'sqlite', 'pgsql'])) { - throw new ValidationFailed('Currently, only MySQL/MariaDB and SQLite are supported.'); + if (! in_array($this->driver, ['mysql', 'mariadb', 'sqlite', 'pgsql'])) { + throw new ValidationFailed('Currently, only MySQL, MariaDB, SQLite and PostgreSQL are supported.'); } - if (in_array($this->driver, ['mysql', 'pgsql']) && empty($this->host)) { + if (in_array($this->driver, ['mysql', 'mariadb', 'pgsql']) && empty($this->host)) { throw new ValidationFailed('Please specify the hostname of your database server.'); } - if (in_array($this->driver, ['mysql', 'pgsql']) && ($this->port < 1 || $this->port > 65535)) { + if (in_array($this->driver, ['mysql', 'mariadb', 'pgsql']) && ($this->port < 1 || $this->port > 65535)) { throw new ValidationFailed('Please provide a valid port number between 1 and 65535.'); } @@ -58,7 +58,7 @@ private function validate(): void throw new ValidationFailed('Please specify the database name.'); } - if (in_array($this->driver, ['mysql', 'pgsql']) && empty($this->username)) { + if (in_array($this->driver, ['mysql', 'mariadb', 'pgsql']) && empty($this->username)) { throw new ValidationFailed('Please specify the username for accessing the database.'); } @@ -84,7 +84,7 @@ public function prepare(Paths $paths): void private function driverOptions(): array { return match ($this->driver) { - 'mysql' => [ + 'mysql', 'mariadb' => [ 'host' => $this->host, 'port' => $this->port, 'username' => $this->username, diff --git a/framework/core/src/Install/Steps/ConnectToDatabase.php b/framework/core/src/Install/Steps/ConnectToDatabase.php index 2fa1290a1a..8e66328a3e 100644 --- a/framework/core/src/Install/Steps/ConnectToDatabase.php +++ b/framework/core/src/Install/Steps/ConnectToDatabase.php @@ -12,9 +12,11 @@ use Closure; use Flarum\Install\DatabaseConfig; use Flarum\Install\Step; +use Illuminate\Database\Connectors\MariaDbConnector; use Illuminate\Database\Connectors\MySqlConnector; use Illuminate\Database\Connectors\PostgresConnector; use Illuminate\Database\Connectors\SQLiteConnector; +use Illuminate\Database\MariaDbConnection; use Illuminate\Database\MySqlConnection; use Illuminate\Database\PostgresConnection; use Illuminate\Database\SQLiteConnection; @@ -42,6 +44,7 @@ public function run(): void match ($config['driver']) { 'mysql' => $this->mysql($config), + 'mariadb' => $this->mariadb($config), 'pgsql' => $this->pgsql($config), 'sqlite' => $this->sqlite($config), default => throw new InvalidArgumentException('Unsupported database driver: '.$config['driver']), @@ -74,6 +77,26 @@ private function mysql(array $config): void ); } + private function mariadb(array $config): void + { + $pdo = (new MariaDbConnector())->connect($config); + + $version = $pdo->query('SELECT VERSION()')->fetchColumn(); + + if (version_compare($version, '10.3.0', '<')) { + throw new RangeException("MariaDB version ($version) too low. You need at least MariaDB 10.3"); + } + + ($this->store)( + new MariaDbConnection( + $pdo, + $config['database'], + $config['prefix'], + $config + ) + ); + } + private function pgsql(array $config): void { $pdo = (new PostgresConnector)->connect($config); diff --git a/framework/core/src/Post/Filter/FulltextFilter.php b/framework/core/src/Post/Filter/FulltextFilter.php index d8774da10b..ca8b2ed001 100644 --- a/framework/core/src/Post/Filter/FulltextFilter.php +++ b/framework/core/src/Post/Filter/FulltextFilter.php @@ -29,7 +29,7 @@ public function __construct( public function search(SearchState $state, string $value): void { match ($state->getQuery()->getConnection()->getDriverName()) { - 'mysql' => $this->mysql($state, $value), + 'mysql', 'mariadb' => $this->mysql($state, $value), 'pgsql' => $this->pgsql($state, $value), 'sqlite' => $this->sqlite($state, $value), default => throw new RuntimeException('Unsupported database driver: '.$state->getQuery()->getConnection()->getDriverName()), diff --git a/framework/core/views/install/install.php b/framework/core/views/install/install.php index d94ef7cf95..8f08032bd7 100644 --- a/framework/core/views/install/install.php +++ b/framework/core/views/install/install.php @@ -25,6 +25,7 @@ @@ -35,7 +36,7 @@ -
+
diff --git a/php-packages/testing/src/integration/Setup/SetupScript.php b/php-packages/testing/src/integration/Setup/SetupScript.php index 0d0f2471db..a9987c3965 100644 --- a/php-packages/testing/src/integration/Setup/SetupScript.php +++ b/php-packages/testing/src/integration/Setup/SetupScript.php @@ -41,7 +41,7 @@ public function __construct() $this->driver = getenv('DB_DRIVER') ?: 'mysql'; $this->host = getenv('DB_HOST') ?: 'localhost'; $this->port = intval(getenv('DB_PORT') ?: match ($this->driver) { - 'mysql' => 3306, + 'mysql', 'mariadb' => 3306, 'pgsql' => 5432, default => 0, });