Skip to content

Commit

Permalink
MNT Update utf8 aliases for mysql 8 and mariadb 10.6
Browse files Browse the repository at this point in the history
  • Loading branch information
emteknetnz committed Jul 21, 2022
1 parent 9db1cd0 commit 674e6d9
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 6 deletions.
11 changes: 7 additions & 4 deletions tests/php/ORM/MySQLPDOConnectorTest.php
Expand Up @@ -9,6 +9,7 @@
use SilverStripe\Dev\TestOnly;
use SilverStripe\ORM\Tests\MySQLPDOConnectorTest\PDOConnector;
use SilverStripe\ORM\DB;
use SilverStripe\Tests\ORM\Utf8\Utf8TestHelper;

/**
* @requires extension PDO
Expand Down Expand Up @@ -38,8 +39,9 @@ public function testConnectionCharsetControl($charset, $defaultCollation)
$cset = $connection->query('show variables like "character_set_connection"')->fetch(PDO::FETCH_NUM)[1];
$collation = $connection->query('show variables like "collation_connection"')->fetch(PDO::FETCH_NUM)[1];

$this->assertEquals($charset, $cset);
$this->assertEquals($defaultCollation, $collation);
$helper = new Utf8TestHelper();
$this->assertEquals($helper->getUpdatedUtfCharsetForCurrentDB($charset), $cset);
$this->assertEquals($helper->getUpdatedUtfCollationForCurrentDB($defaultCollation), $collation);

unset($cset, $connection, $connector, $config);
}
Expand All @@ -66,8 +68,9 @@ public function testConnectionCollationControl($charset, $defaultCollation, $cus
$cset = $connection->query('show variables like "character_set_connection"')->fetch(PDO::FETCH_NUM)[1];
$collation = $connection->query('show variables like "collation_connection"')->fetch(PDO::FETCH_NUM)[1];

$this->assertEquals($charset, $cset);
$this->assertEquals($customCollation, $collation);
$helper = new Utf8TestHelper();
$this->assertEquals($helper->getUpdatedUtfCharsetForCurrentDB($charset), $cset);
$this->assertEquals($helper->getUpdatedUtfCollationForCurrentDB($customCollation), $collation);

unset($cset, $connection, $connector, $config);
}
Expand Down
10 changes: 8 additions & 2 deletions tests/php/ORM/MySQLiConnectorTest.php
Expand Up @@ -6,6 +6,7 @@
use SilverStripe\Dev\TestOnly;
use SilverStripe\ORM\Tests\MySQLiConnectorTest\MySQLiConnector;
use SilverStripe\ORM\DB;
use SilverStripe\Tests\ORM\Utf8\Utf8TestHelper;

/**
* @requires extension mysqli
Expand All @@ -31,6 +32,10 @@ public function testConnectionCharsetControl($charset, $defaultCollation)

$cset = $connection->get_charset();

// Note: we do not need to update the utf charset here because mysqli with newer
// version of mysql/mariadb still self-reports as 'utf8' rather than 'utf8mb3'
// This is unlike self::testConnectionCollationControl()
// And also unlike MySQLPDOConnectorTest::testConnectionCharsetControl()
$this->assertEquals($charset, $cset->charset);
$this->assertEquals($defaultCollation, $cset->collation);

Expand Down Expand Up @@ -77,8 +82,9 @@ public function testConnectionCollationControl($charset, $defaultCollation, $cus
$cset = $connection->query('show variables like "character_set_connection"')->fetch_array()[1];
$collation = $connection->query('show variables like "collation_connection"')->fetch_array()[1];

$this->assertEquals($charset, $cset);
$this->assertEquals($customCollation, $collation);
$helper = new Utf8TestHelper();
$this->assertEquals($helper->getUpdatedUtfCharsetForCurrentDB($charset), $cset);
$this->assertEquals($helper->getUpdatedUtfCollationForCurrentDB($customCollation), $collation);

$connection->close();
unset($cset, $connection, $connector, $config);
Expand Down
69 changes: 69 additions & 0 deletions tests/php/ORM/Utf8/Utf8TestHelper.php
@@ -0,0 +1,69 @@
<?php

namespace SilverStripe\Tests\ORM\Utf8;

use SilverStripe\Dev\TestOnly;
use SilverStripe\ORM\DB;

class Utf8TestHelper implements TestOnly
{
/**
* @var string|null
*/
private $dbVersion = null;

public function getUpdatedUtfCharsetForCurrentDB(string $charset): string
{
if ($charset !== 'utf8') {
return $charset;
}
return $this->isMySqlGte80() || $this->isMariaDBGte106() ? 'utf8mb3' : 'utf8';
}

public function getUpdatedUtfCollationForCurrentDB(string $collation): string
{
if ($collation === 'utf8_general_ci') {
return $this->isMariaDBGte106() ? 'utf8mb3_general_ci' : 'utf8_general_ci';
}
if ($collation === 'utf8_unicode_520_ci') {
return $this->isMariaDBGte106() ? 'utf8mb3_unicode_520_ci' : 'utf8_unicode_520_ci';
}
return $collation;
}

/**
* MySQL has used utf8 as an alias for utf8mb3
* Beginning with MySQL 8.0.28, utf8mb3 is used
* https://dev.mysql.com/doc/refman/8.0/en/charset-unicode-utf8mb3.html
*/
private function isMySqlGte80(): bool
{
// Example MySQL version: 8.0.29
if (preg_match('#^([0-9]+)\.[0-9]+\.[0-9]+$#', $this->getDBVersion(), $m)) {
return (int) $m[1] >= 8;
}
return false;
}

/**
* Until MariaDB 10.5, utf8mb3 was an alias for utf8.
* From MariaDB 10.6, utf8 is by default an alias for utf8mb3
* https://mariadb.com/kb/en/unicode/
*/
private function isMariaDBGte106(): bool
{
// Example mariadb version: 5.5.5-10.6.8-mariadb-1:10.6.8+maria~focal
if (preg_match('#([0-9]+)\.([0-9]+)\.[0-9]+-mariadb#', $this->getDBVersion(), $m)) {
return (int) $m[1] >= 11 || ((int) $m[1] >= 10 && (int) $m[2] >= 6);
}
return false;
}

private function getDBVersion(): string
{
if (is_null($this->dbVersion)) {
$this->dbVersion = strtolower(DB::get_conn()->getVersion());
}
return $this->dbVersion;
}
}

0 comments on commit 674e6d9

Please sign in to comment.