diff --git a/ChangeLog b/ChangeLog
index 94573dafde..763f046036 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -77,6 +77,11 @@ phpMyAdmin - ChangeLog
- issue #16842 Fixed missing password modes on PerconaDB
- issue #16947 Fix "Change login information" form not working
- issue #17004 Fix Advisor for MariaDB >= 10.5 because of removed "innodb_log_files_in_group" variable
+- issue #17037 Fix change structure does not surface errors
+- issue #17016 Fixed online Transaction, errors not reported on structure edit
+- issue #17042 Fix SQL escaping bug on DB name with special chars on submit query with rollback option
+- issue #17027 Better handle the display of sorted binary columns in results summary
+- issue #16398 Quote non numeric values on parameterized queries
5.1.1 (2021-06-04)
- issue #13325 Fixed created procedure shows up in triggers and events and vice-versa
diff --git a/libraries/advisory_rules_generic.php b/libraries/advisory_rules_generic.php
index a9d6fc0e6d..6a65948e68 100644
--- a/libraries/advisory_rules_generic.php
+++ b/libraries/advisory_rules_generic.php
@@ -642,7 +642,7 @@ return [
// From MariaDB 10.5, there is 1 redo log.
// For MariaDB 10.4 and before, the number of redo log files is configured
// by the innodb_log_files_in_group system variable.
- 'formula' => '(innodb_log_file_size * 1)/ innodb_buffer_pool_size * 100',
+ 'formula' => 'innodb_log_file_size / innodb_buffer_pool_size * 100',
'test' => 'value < 20 && innodb_log_file_size / (1024 * 1024) < 256',
'issue' => __(
'The InnoDB log file size is not an appropriate size, in relation to the InnoDB buffer pool.'
diff --git a/libraries/classes/Controllers/ImportController.php b/libraries/classes/Controllers/ImportController.php
index bb475fb9d7..2b751d8b52 100644
--- a/libraries/classes/Controllers/ImportController.php
+++ b/libraries/classes/Controllers/ImportController.php
@@ -34,6 +34,7 @@ use function ini_set;
use function intval;
use function is_array;
use function is_link;
+use function is_numeric;
use function is_uploaded_file;
use function mb_strlen;
use function mb_strtolower;
@@ -176,17 +177,22 @@ final class ImportController extends AbstractController
) {
$parameters = $_POST['parameters'];
foreach ($parameters as $parameter => $replacement) {
+ $replacementValue = $this->dbi->escapeString($replacement);
+ if (! is_numeric($replacementValue)) {
+ $replacementValue = '\'' . $replacementValue . '\'';
+ }
+
$quoted = preg_quote($parameter, '/');
// making sure that :param does not apply values to :param1
$sql_query = preg_replace(
'/' . $quoted . '([^a-zA-Z0-9_])/',
- $this->dbi->escapeString($replacement) . '${1}',
+ $replacementValue . '${1}',
$sql_query
);
// for parameters the appear at the end of the string
$sql_query = preg_replace(
'/' . $quoted . '$/',
- $this->dbi->escapeString($replacement),
+ $replacementValue,
$sql_query
);
}
diff --git a/libraries/classes/Controllers/Table/StructureController.php b/libraries/classes/Controllers/Table/StructureController.php
index 9f1dad2dc4..467a6a3d98 100644
--- a/libraries/classes/Controllers/Table/StructureController.php
+++ b/libraries/classes/Controllers/Table/StructureController.php
@@ -1220,11 +1220,11 @@ class StructureController extends AbstractController
$this->dbi->query($revert_query);
$this->response->setRequestStatus(false);
- $this->response->addJSON(
- 'message',
- Message::rawError(
- __('Query error') . ':
' . $orig_error
- )
+ $message = Message::rawError(
+ __('Query error') . ':
' . $orig_error
+ );
+ $this->response->addHTML(
+ Generator::getMessage($message, $sql_query, 'error')
);
$regenerate = true;
}
diff --git a/libraries/classes/Display/Results.php b/libraries/classes/Display/Results.php
index f65b249675..c54a60c9c0 100644
--- a/libraries/classes/Display/Results.php
+++ b/libraries/classes/Display/Results.php
@@ -4296,9 +4296,10 @@ class Results
// check for non printable sorted row data
$meta = $fieldsMeta[$sortedColumnIndex];
- $isBlobOrGeometry = $meta->isType(FieldMetadata::TYPE_BLOB) || $meta->isMappedTypeGeometry;
+ $isBlobOrGeometryOrBinary = $meta->isType(FieldMetadata::TYPE_BLOB)
+ || $meta->isMappedTypeGeometry || $meta->isBinary;
- if ($isBlobOrGeometry) {
+ if ($isBlobOrGeometryOrBinary) {
$columnForFirstRow = $this->handleNonPrintableContents(
$meta->getMappedType(),
$row[$sortedColumnIndex],
@@ -4328,7 +4329,7 @@ class Results
// check for non printable sorted row data
$meta = $fieldsMeta[$sortedColumnIndex];
- if ($isBlobOrGeometry) {
+ if ($isBlobOrGeometryOrBinary) {
$columnForLastRow = $this->handleNonPrintableContents(
$meta->getMappedType(),
$row[$sortedColumnIndex],
diff --git a/libraries/classes/Import.php b/libraries/classes/Import.php
index 58ce392175..07e27a5816 100644
--- a/libraries/classes/Import.php
+++ b/libraries/classes/Import.php
@@ -1800,8 +1800,8 @@ class Import
// Query to check if table is 'Transactional'.
$checkQuery = 'SELECT `ENGINE` FROM `information_schema`.`tables` '
- . 'WHERE `table_name` = "' . $table . '" '
- . 'AND `table_schema` = "' . $db . '" '
+ . 'WHERE `table_name` = "' . $dbi->escapeString($table) . '" '
+ . 'AND `table_schema` = "' . $dbi->escapeString($db) . '" '
. 'AND UPPER(`engine`) IN ("'
. implode('", "', $transactionalEngines)
. '")';
diff --git a/test/classes/Controllers/ImportControllerTest.php b/test/classes/Controllers/ImportControllerTest.php
new file mode 100644
index 0000000000..15eb998fb9
--- /dev/null
+++ b/test/classes/Controllers/ImportControllerTest.php
@@ -0,0 +1,73 @@
+ 'Saint-Louis - Châteaulin', ':1' => '4'];
+ $_POST['sql_query'] = 'SELECT A.*' . "\n"
+ . 'FROM table1 A' . "\n"
+ . 'WHERE A.nomEtablissement = :nomEta AND foo = :1 AND `:a` IS NULL';
+ $sql_query = $_POST['sql_query'];
+
+ $this->dummyDbi->addResult(
+ 'SELECT A.* FROM table1 A WHERE A.nomEtablissement = \'Saint-Louis - Châteaulin\''
+ . ' AND foo = 4 AND `:a` IS NULL LIMIT 0, 25',
+ []
+ );
+
+ $this->dummyDbi->addResult(
+ 'SHOW CREATE TABLE `pma_test`.`table1`',
+ []
+ );
+
+ $this->dummyDbi->addResult(
+ 'SHOW FULL COLUMNS FROM `pma_test`.`table1`',
+ []
+ );
+
+ /** @var ImportController $importController */
+ $importController = $containerBuilder->get(ImportController::class);
+ $importController->index();
+ $this->assertResponseWasSuccessfull();
+
+ $this->assertStringContainsString(
+ 'MySQL returned an empty result set (i.e. zero rows).',
+ $this->getResponseHtmlResult()
+ );
+
+ $this->assertStringContainsString(
+ 'SELECT A.*' . "\n" . 'FROM table1 A' . "\n"
+ . 'WHERE A.nomEtablissement = \'Saint-Louis - Châteaulin\' AND foo = 4 AND `:a` IS NULL',
+ $this->getResponseHtmlResult()
+ );
+
+ $this->assertAllQueriesConsumed();
+ }
+}