Merge branch 'QA_5_1'
Signed-off-by: William Desportes <williamdes@wdes.fr>
This commit is contained in:
commit
919ce3975f
2
.github/workflows/test-selenium.yml
vendored
2
.github/workflows/test-selenium.yml
vendored
@ -54,6 +54,8 @@ jobs:
|
||||
db-server: ["mysql:5.7"]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Refresh apt cache
|
||||
run: sudo apt-get update
|
||||
- name: Install gettext
|
||||
run: sudo apt-get install -y gettext
|
||||
- name: Generate mo files
|
||||
|
||||
@ -121,6 +121,8 @@ phpMyAdmin - ChangeLog
|
||||
- issue #16920 Fixed "Uncaught TypeError: PhpMyAdmin\Import::detectType()" on ODS import
|
||||
- issue #16926 Fixed ODS import warning: Undefined array key "ods_empty_rows"
|
||||
- issue #16888 Fixed JS error on renaming tables in saved Designer page
|
||||
- issue #16504 Fixed create view dialog is too big and won't scroll (on small screens)
|
||||
- issue #16931 Fixed php notice "Undefined index: utf8mb3" on MySQL 8.0.11+ servers with default utf8 server charset
|
||||
|
||||
5.1.0 (2021-02-24)
|
||||
- issue #15350 Change Media (MIME) type references to Media type
|
||||
|
||||
@ -4565,6 +4565,7 @@ Functions.createViewDialog = function ($this) {
|
||||
var $dialog = $('<div></div>').attr('id', 'createViewDialog').append(data.message).dialog({
|
||||
width: 600,
|
||||
minWidth: 400,
|
||||
height: $(window).height(),
|
||||
modal: true,
|
||||
buttons: buttonOptions,
|
||||
title: Messages.strCreateView,
|
||||
|
||||
@ -159,7 +159,28 @@ class Charsets
|
||||
$serverCharset = $dbi->fetchValue('SELECT @@character_set_server;');
|
||||
}
|
||||
|
||||
self::$serverCharset = self::$charsets[$serverCharset];
|
||||
self::$serverCharset = self::$charsets[$serverCharset] ?? null;
|
||||
|
||||
// MySQL 8.0.11+ fallback, issue #16931
|
||||
if (self::$serverCharset === null && $serverCharset === 'utf8mb3') {
|
||||
// See: https://dev.mysql.com/doc/relnotes/mysql/8.0/en/news-8-0-11.html#mysqld-8-0-11-charset
|
||||
// The utf8mb3 character set will be replaced by utf8mb4 in a future MySQL version.
|
||||
// The utf8 character set is currently an alias for utf8mb3,
|
||||
// but will at that point become a reference to utf8mb4.
|
||||
// To avoid ambiguity about the meaning of utf8,
|
||||
// consider specifying utf8mb4 explicitly for character set references instead of utf8.
|
||||
// Warning: #3719 'utf8' is currently an alias for the character set UTF8MB3 [...]
|
||||
return self::$charsets['utf8'];
|
||||
}
|
||||
|
||||
if (self::$serverCharset === null) {// Fallback in case nothing is found
|
||||
return Charset::fromServer(
|
||||
[
|
||||
'Charset' => __('Unknown'),
|
||||
'Description' => __('Unknown'),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
return self::$serverCharset;
|
||||
}
|
||||
|
||||
@ -39,6 +39,20 @@ abstract class AbstractTestCase extends TestCase
|
||||
'__PHPUNIT_BOOTSTRAP',
|
||||
];
|
||||
|
||||
/**
|
||||
* The DatabaseInterface loaded by setGlobalDbi
|
||||
*
|
||||
* @var DatabaseInterface
|
||||
*/
|
||||
protected $dbi;
|
||||
|
||||
/**
|
||||
* The DbiDummy loaded by setGlobalDbi
|
||||
*
|
||||
* @var DbiDummy
|
||||
*/
|
||||
protected $dummyDbi;
|
||||
|
||||
/**
|
||||
* Prepares environment for the test.
|
||||
* Clean all variables
|
||||
@ -126,7 +140,9 @@ abstract class AbstractTestCase extends TestCase
|
||||
protected function setGlobalDbi(): void
|
||||
{
|
||||
global $dbi;
|
||||
$dbi = DatabaseInterface::load(new DbiDummy());
|
||||
$this->dummyDbi = new DbiDummy();
|
||||
$this->dbi = DatabaseInterface::load($this->dummyDbi);
|
||||
$dbi = $this->dbi;
|
||||
}
|
||||
|
||||
protected function setGlobalConfig(): void
|
||||
|
||||
@ -17,11 +17,65 @@ class CharsetsTest extends AbstractTestCase
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
parent::setGlobalDbi();
|
||||
$GLOBALS['server'] = 0;
|
||||
$GLOBALS['cfg']['DBG']['sql'] = false;
|
||||
$GLOBALS['cfg']['Server']['DisableIS'] = false;
|
||||
}
|
||||
|
||||
public function testGetServerCharset(): void
|
||||
{
|
||||
$this->dummyDbi->addResult(
|
||||
'SHOW SESSION VARIABLES LIKE \'character_set_server\';',
|
||||
[
|
||||
[
|
||||
'character_set_server',
|
||||
'utf8mb3',
|
||||
],
|
||||
],
|
||||
[
|
||||
'Variable_name',
|
||||
'Value',
|
||||
]
|
||||
);
|
||||
$this->dummyDbi->addResult(
|
||||
'SHOW SESSION VARIABLES LIKE \'character_set_server\';',
|
||||
false
|
||||
);
|
||||
$this->dummyDbi->addResult(
|
||||
'SELECT @@character_set_server;',
|
||||
false
|
||||
);
|
||||
$this->dummyDbi->addResult(
|
||||
'SHOW SESSION VARIABLES LIKE \'character_set_server\';',
|
||||
false
|
||||
);
|
||||
$this->dummyDbi->addResult(
|
||||
'SELECT @@character_set_server;',
|
||||
[
|
||||
['utf8mb3'],
|
||||
]
|
||||
);
|
||||
|
||||
$charset = Charsets::getServerCharset(
|
||||
$GLOBALS['dbi'],
|
||||
$GLOBALS['cfg']['Server']['DisableIS']
|
||||
);
|
||||
$this->assertSame('utf8', $charset->getName());
|
||||
|
||||
$charset = Charsets::getServerCharset(
|
||||
$GLOBALS['dbi'],
|
||||
$GLOBALS['cfg']['Server']['DisableIS']
|
||||
);
|
||||
$this->assertSame('Unknown', $charset->getName());
|
||||
|
||||
$charset = Charsets::getServerCharset(
|
||||
$GLOBALS['dbi'],
|
||||
$GLOBALS['cfg']['Server']['DisableIS']
|
||||
);
|
||||
$this->assertSame('utf8', $charset->getName());
|
||||
}
|
||||
|
||||
public function testFindCollationByName(): void
|
||||
{
|
||||
$this->assertNull(Charsets::findCollationByName(
|
||||
|
||||
@ -20,9 +20,6 @@ use stdClass;
|
||||
*/
|
||||
class DatabaseInterfaceTest extends AbstractTestCase
|
||||
{
|
||||
/** @var DatabaseInterface */
|
||||
private $dbi;
|
||||
|
||||
/**
|
||||
* Configures test parameters.
|
||||
*/
|
||||
@ -47,20 +44,19 @@ class DatabaseInterfaceTest extends AbstractTestCase
|
||||
public function testGetCurrentUser($value, string $string, array $expected): void
|
||||
{
|
||||
SessionCache::remove('mysql_cur_user');
|
||||
parent::setGlobalDbi();
|
||||
|
||||
$extension = new DbiDummy();
|
||||
$extension->setResult('SELECT CURRENT_USER();', $value);
|
||||
|
||||
$dbi = new DatabaseInterface($extension);
|
||||
$this->dummyDbi->addResult('SELECT CURRENT_USER();', $value);
|
||||
$this->dummyDbi->addResult('SELECT CURRENT_USER();', $value);
|
||||
|
||||
$this->assertEquals(
|
||||
$expected,
|
||||
$dbi->getCurrentUserAndHost()
|
||||
$this->dbi->getCurrentUserAndHost()
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
$string,
|
||||
$dbi->getCurrentUser()
|
||||
$this->dbi->getCurrentUser()
|
||||
);
|
||||
}
|
||||
|
||||
@ -277,15 +273,13 @@ class DatabaseInterfaceTest extends AbstractTestCase
|
||||
public function testIsAmazonRdsData(array $value, bool $expected): void
|
||||
{
|
||||
SessionCache::remove('is_amazon_rds');
|
||||
parent::setGlobalDbi();
|
||||
|
||||
$extension = new DbiDummy();
|
||||
$extension->setResult('SELECT @@basedir', $value);
|
||||
|
||||
$dbi = new DatabaseInterface($extension);
|
||||
$this->dummyDbi->addResult('SELECT @@basedir', $value);
|
||||
|
||||
$this->assertEquals(
|
||||
$expected,
|
||||
$dbi->isAmazonRds()
|
||||
$this->dbi->isAmazonRds()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -38,8 +38,34 @@ use const MYSQLI_TYPE_STRING;
|
||||
*/
|
||||
class DbiDummy implements DbiExtension
|
||||
{
|
||||
/** @var array */
|
||||
private $queries = [];
|
||||
/**
|
||||
* First in, last out queries
|
||||
*
|
||||
* The results will be distributed in the filo way
|
||||
*
|
||||
* @var array
|
||||
* @phpstan-var array{
|
||||
* 'query': string,
|
||||
* 'result': ((int[]|string[]|array{string: string})[])|bool|empty-array,
|
||||
* 'columns'?: string[],
|
||||
* 'metadata'?: object[]|empty-array,
|
||||
* 'used'?: bool,
|
||||
* 'pos'?: int
|
||||
* }[]
|
||||
*/
|
||||
private $filoQueries = [];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
* @phpstan-var array{
|
||||
* 'query': string,
|
||||
* 'result': ((int[]|string[]|array{string: string})[])|bool|empty-array,
|
||||
* 'columns'?: string[],
|
||||
* 'metadata'?: object[]|empty-array,
|
||||
* 'pos'?: int
|
||||
* }[]
|
||||
*/
|
||||
private $dummyQueries = [];
|
||||
|
||||
public const OFFSET_GLOBAL = 1000;
|
||||
|
||||
@ -80,6 +106,33 @@ class DbiDummy implements DbiExtension
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return false|int|null
|
||||
*/
|
||||
private function findFiloQuery(string $query)
|
||||
{
|
||||
for ($i = 0, $nb = count($this->filoQueries); $i < $nb; $i++) {
|
||||
if ($this->filoQueries[$i]['query'] !== $query) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($this->filoQueries[$i]['used'] ?? false) {
|
||||
continue;// Is has already been used
|
||||
}
|
||||
|
||||
$this->filoQueries[$i]['pos'] = 0;
|
||||
$this->filoQueries[$i]['used'] = true;
|
||||
|
||||
if (! is_array($this->filoQueries[$i]['result'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $i;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* runs a query and returns the result
|
||||
*
|
||||
@ -92,26 +145,18 @@ class DbiDummy implements DbiExtension
|
||||
public function realQuery($query, $link = null, $options = 0)
|
||||
{
|
||||
$query = trim((string) preg_replace('/ */', ' ', str_replace("\n", ' ', $query)));
|
||||
for ($i = 0, $nb = count($this->queries); $i < $nb; $i++) {
|
||||
if ($this->queries[$i]['query'] != $query) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->queries[$i]['pos'] = 0;
|
||||
if (! is_array($this->queries[$i]['result'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $i;
|
||||
$filoQuery = $this->findFiloQuery($query);
|
||||
if ($filoQuery !== null) {// Found a matching query
|
||||
return $filoQuery;
|
||||
}
|
||||
|
||||
for ($i = 0, $nb = count($GLOBALS['dummy_queries']); $i < $nb; $i++) {
|
||||
if ($GLOBALS['dummy_queries'][$i]['query'] != $query) {
|
||||
for ($i = 0, $nb = count($this->dummyQueries); $i < $nb; $i++) {
|
||||
if ($this->dummyQueries[$i]['query'] !== $query) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$GLOBALS['dummy_queries'][$i]['pos'] = 0;
|
||||
if (! is_array($GLOBALS['dummy_queries'][$i]['result'])) {
|
||||
$this->dummyQueries[$i]['pos'] = 0;
|
||||
if (! is_array($this->dummyQueries[$i]['result'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -437,16 +482,21 @@ class DbiDummy implements DbiExtension
|
||||
/**
|
||||
* Adds query result for testing
|
||||
*
|
||||
* @param string $query SQL
|
||||
* @param array|false $result Expected result
|
||||
* @param string $query SQL
|
||||
* @param array|bool $result Expected result
|
||||
* @param string[] $columns The result columns
|
||||
* @param object[] $metadata The result metadata
|
||||
* @phpstan-param (int[]|string[]|array{string: string})[]|bool $result
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setResult($query, $result)
|
||||
public function addResult(string $query, $result, array $columns = [], array $metadata = [])
|
||||
{
|
||||
$this->queries[] = [
|
||||
$this->filoQueries[] = [
|
||||
'query' => $query,
|
||||
'result' => $result,
|
||||
'columns' => $columns,
|
||||
'metadata' => $metadata,
|
||||
];
|
||||
}
|
||||
|
||||
@ -476,10 +526,10 @@ class DbiDummy implements DbiExtension
|
||||
}
|
||||
|
||||
if ($result >= self::OFFSET_GLOBAL) {
|
||||
return $GLOBALS['dummy_queries'][$result - self::OFFSET_GLOBAL];
|
||||
return $this->dummyQueries[$result - self::OFFSET_GLOBAL];
|
||||
}
|
||||
|
||||
return $this->queries[$result];
|
||||
return $this->filoQueries[$result];
|
||||
}
|
||||
|
||||
private function init(): void
|
||||
@ -487,7 +537,7 @@ class DbiDummy implements DbiExtension
|
||||
/**
|
||||
* Array of queries this "driver" supports
|
||||
*/
|
||||
$GLOBALS['dummy_queries'] = [
|
||||
$this->dummyQueries = [
|
||||
[
|
||||
'query' => 'SELECT 1',
|
||||
'result' => [['1']],
|
||||
@ -817,12 +867,24 @@ class DbiDummy implements DbiExtension
|
||||
'Maxlen',
|
||||
],
|
||||
'result' => [
|
||||
[
|
||||
'armscii8',
|
||||
'ARMSCII-8 Armenian',
|
||||
'armscii8_general_ci',
|
||||
'1',
|
||||
],
|
||||
[
|
||||
'utf8',
|
||||
'utf8_general_ci',
|
||||
'UTF-8 Unicode',
|
||||
'3',
|
||||
],
|
||||
[
|
||||
'utf8mb4',
|
||||
'UTF-8 Unicode',
|
||||
'utf8mb4_0900_ai_ci',
|
||||
'4',
|
||||
],
|
||||
[
|
||||
'latin1',
|
||||
'latin1_swedish_ci',
|
||||
@ -848,6 +910,22 @@ class DbiDummy implements DbiExtension
|
||||
'Sortlen',
|
||||
],
|
||||
'result' => [
|
||||
[
|
||||
'utf8mb4_general_ci',
|
||||
'utf8mb4',
|
||||
'45',
|
||||
'Yes',
|
||||
'Yes',
|
||||
'1',
|
||||
],
|
||||
[
|
||||
'armscii8_general_ci',
|
||||
'armscii8',
|
||||
'32',
|
||||
'Yes',
|
||||
'Yes',
|
||||
'1',
|
||||
],
|
||||
[
|
||||
'utf8_general_ci',
|
||||
'utf8',
|
||||
|
||||
Loading…
Reference in New Issue
Block a user