diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -25,6 +25,7 @@ 'AphrontDatabaseTransactionState' => 'aphront/storage/connection/AphrontDatabaseTransactionState.php', 'AphrontDeadlockQueryException' => 'aphront/storage/exception/AphrontDeadlockQueryException.php', 'AphrontDuplicateKeyQueryException' => 'aphront/storage/exception/AphrontDuplicateKeyQueryException.php', + 'AphrontInvalidCredentialsQueryException' => 'aphront/storage/exception/AphrontInvalidCredentialsQueryException.php', 'AphrontIsolatedDatabaseConnection' => 'aphront/storage/connection/AphrontIsolatedDatabaseConnection.php', 'AphrontLockTimeoutQueryException' => 'aphront/storage/exception/AphrontLockTimeoutQueryException.php', 'AphrontMySQLDatabaseConnection' => 'aphront/storage/connection/mysql/AphrontMySQLDatabaseConnection.php', @@ -529,7 +530,7 @@ 'AASTTree' => 'Phobject', 'AbstractDirectedGraph' => 'Phobject', 'AbstractDirectedGraphTestCase' => 'PhutilTestCase', - 'AphrontAccessDeniedQueryException' => 'AphrontRecoverableQueryException', + 'AphrontAccessDeniedQueryException' => 'AphrontQueryException', 'AphrontBaseMySQLDatabaseConnection' => 'AphrontDatabaseConnection', 'AphrontCharacterSetQueryException' => 'AphrontQueryException', 'AphrontConnectionLostQueryException' => 'AphrontRecoverableQueryException', @@ -542,6 +543,7 @@ 'AphrontDatabaseTransactionState' => 'Phobject', 'AphrontDeadlockQueryException' => 'AphrontRecoverableQueryException', 'AphrontDuplicateKeyQueryException' => 'AphrontQueryException', + 'AphrontInvalidCredentialsQueryException' => 'AphrontQueryException', 'AphrontIsolatedDatabaseConnection' => 'AphrontDatabaseConnection', 'AphrontLockTimeoutQueryException' => 'AphrontRecoverableQueryException', 'AphrontMySQLDatabaseConnection' => 'AphrontBaseMySQLDatabaseConnection', diff --git a/src/aphront/storage/connection/mysql/AphrontBaseMySQLDatabaseConnection.php b/src/aphront/storage/connection/mysql/AphrontBaseMySQLDatabaseConnection.php --- a/src/aphront/storage/connection/mysql/AphrontBaseMySQLDatabaseConnection.php +++ b/src/aphront/storage/connection/mysql/AphrontBaseMySQLDatabaseConnection.php @@ -275,42 +275,69 @@ $this->throwQueryCodeException($errno, $error); } - protected function throwQueryCodeException($errno, $error) { - $exmsg = "#{$errno}: {$error}"; + private function throwCommonException($errno, $error) { + $message = pht('#%d: %s', $errno, $error); switch ($errno) { case 2013: // Connection Dropped - throw new AphrontConnectionLostQueryException($exmsg); + throw new AphrontConnectionLostQueryException($message); case 2006: // Gone Away $more = pht( "This error may occur if your MySQL '%s' or '%s' ". "configuration values are set too low.", 'wait_timeout', 'max_allowed_packet'); - throw new AphrontConnectionLostQueryException("{$exmsg}\n\n{$more}"); + throw new AphrontConnectionLostQueryException("{$message}\n\n{$more}"); case 1213: // Deadlock - throw new AphrontDeadlockQueryException($exmsg); + throw new AphrontDeadlockQueryException($message); case 1205: // Lock wait timeout exceeded - throw new AphrontLockTimeoutQueryException($exmsg); + throw new AphrontLockTimeoutQueryException($message); case 1062: // Duplicate Key // NOTE: In some versions of MySQL we get a key name back here, but // older versions just give us a key index ("key 2") so it's not // portable to parse the key out of the error and attach it to the // exception. - throw new AphrontDuplicateKeyQueryException($exmsg); + throw new AphrontDuplicateKeyQueryException($message); case 1044: // Access denied to database - case 1045: // Access denied (auth) case 1142: // Access denied to table case 1143: // Access denied to column - throw new AphrontAccessDeniedQueryException($exmsg); + throw new AphrontAccessDeniedQueryException($message); + case 1045: // Access denied (auth) + throw new AphrontInvalidCredentialsQueryException($message); case 1146: // No such table case 1049: // No such database case 1054: // Unknown column "..." in field list - throw new AphrontSchemaQueryException($exmsg); - default: - // TODO: 1064 is syntax error, and quite terrible in production. - throw new AphrontQueryException($exmsg); + throw new AphrontSchemaQueryException($message); } + + // TODO: 1064 is syntax error, and quite terrible in production. + + return null; + } + + protected function throwConnectionException($errno, $error, $user, $host) { + $this->throwCommonException($errno, $error); + + $message = pht( + 'Attempt to connect to %s@%s failed with error #%d: %s.', + $user, + $host, + $errno, + $error); + + throw new AphrontConnectionQueryException($message, $errno); + } + + + protected function throwQueryCodeException($errno, $error) { + $this->throwCommonException($errno, $error); + + $message = pht( + '#%d: %s', + $errno, + $error); + + throw new AphrontQueryException($message, $errno); } /** diff --git a/src/aphront/storage/connection/mysql/AphrontMySQLDatabaseConnection.php b/src/aphront/storage/connection/mysql/AphrontMySQLDatabaseConnection.php --- a/src/aphront/storage/connection/mysql/AphrontMySQLDatabaseConnection.php +++ b/src/aphront/storage/connection/mysql/AphrontMySQLDatabaseConnection.php @@ -61,14 +61,7 @@ if (!$conn) { $errno = mysql_errno(); $error = mysql_error(); - throw new AphrontConnectionQueryException( - pht( - 'Attempt to connect to %s@%s failed with error #%d: %s.', - $user, - $host, - $errno, - $error), - $errno); + $this->throwConnectionException($errno, $error, $user, $host); } if ($database !== null) { diff --git a/src/aphront/storage/connection/mysql/AphrontMySQLiDatabaseConnection.php b/src/aphront/storage/connection/mysql/AphrontMySQLiDatabaseConnection.php --- a/src/aphront/storage/connection/mysql/AphrontMySQLiDatabaseConnection.php +++ b/src/aphront/storage/connection/mysql/AphrontMySQLiDatabaseConnection.php @@ -69,14 +69,7 @@ $errno = $conn->connect_errno; if ($errno) { $error = $conn->connect_error; - throw new AphrontConnectionQueryException( - pht( - 'Attempt to connect to %s@%s failed with error #%d: %s.', - $user, - $host, - $errno, - $error), - $errno); + $this->throwConnectionException($errno, $error, $user, $host); } $ok = @$conn->set_charset('utf8mb4'); diff --git a/src/aphront/storage/exception/AphrontAccessDeniedQueryException.php b/src/aphront/storage/exception/AphrontAccessDeniedQueryException.php --- a/src/aphront/storage/exception/AphrontAccessDeniedQueryException.php +++ b/src/aphront/storage/exception/AphrontAccessDeniedQueryException.php @@ -1,4 +1,4 @@