From 7198bd7db784d4a2dc4890106e586f0b607ce080 Mon Sep 17 00:00:00 2001 From: epriestley Date: Tue, 27 Aug 2019 15:27:25 -0700 Subject: [PATCH] When "utf8mb4" is available, use it as the default client charset when invoking standalone "mysql" commands Summary: Fixes T13390. We have some old code which doesn't dynamically select between "utf8mb4" and "utf8". This can lead to dumping utf8mb4 data over a utf8 connection in `bin/storage dump`, which possibly corrupts some emoji/whales. Instead, prefer "utf8mb4" if it's available. Test Plan: Ran `bin/storage dump` and `bin/storage shell`, saw sub-commands select utf8mb4 as the client charset. Maniphest Tasks: T13390 Differential Revision: https://secure.phabricator.com/D20742 --- .../management/PhabricatorStorageManagementAPI.php | 8 ++++++++ .../workflow/PhabricatorStorageManagementDumpWorkflow.php | 4 +++- .../PhabricatorStorageManagementShellWorkflow.php | 4 ++-- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/infrastructure/storage/management/PhabricatorStorageManagementAPI.php b/src/infrastructure/storage/management/PhabricatorStorageManagementAPI.php index e66ba784f7..b838c8a5d9 100644 --- a/src/infrastructure/storage/management/PhabricatorStorageManagementAPI.php +++ b/src/infrastructure/storage/management/PhabricatorStorageManagementAPI.php @@ -298,6 +298,14 @@ final class PhabricatorStorageManagementAPI extends Phobject { return self::isCharacterSetAvailableOnConnection($character_set, $conn); } + public function getClientCharset() { + if ($this->isCharacterSetAvailable('utf8mb4')) { + return 'utf8mb4'; + } else { + return 'utf8'; + } + } + public static function isCharacterSetAvailableOnConnection( $character_set, AphrontDatabaseConnection $conn) { diff --git a/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementDumpWorkflow.php b/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementDumpWorkflow.php index 28b188a873..3a18578a30 100644 --- a/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementDumpWorkflow.php +++ b/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementDumpWorkflow.php @@ -179,7 +179,9 @@ final class PhabricatorStorageManagementDumpWorkflow $argv = array(); $argv[] = '--hex-blob'; $argv[] = '--single-transaction'; - $argv[] = '--default-character-set=utf8'; + + $argv[] = '--default-character-set'; + $argv[] = $api->getClientCharset(); if ($args->getArg('for-replica')) { $argv[] = '--master-data'; diff --git a/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementShellWorkflow.php b/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementShellWorkflow.php index 0bf185a086..f376ea3e14 100644 --- a/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementShellWorkflow.php +++ b/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementShellWorkflow.php @@ -31,8 +31,8 @@ final class PhabricatorStorageManagementShellWorkflow } return phutil_passthru( - 'mysql --protocol=TCP --default-character-set=utf8mb4 '. - '-u %s %C -h %s %C', + 'mysql --protocol=TCP --default-character-set %R -u %s %C -h %s %C', + $api->getClientCharset(), $api->getUser(), $flag_password, $host,