namespace Cli\Services;
use Exception;
+use Symfony\Component\Process\Exception\ProcessTimedOutException;
class MySqlRunner
{
}
}
+ protected function createOptionsFile(): string
+ {
+ $path = tempnam(sys_get_temp_dir(), 'bs-cli-mysql-opts');
+ $password = str_replace('\\', '\\\\', $this->password);
+ $contents = "[client]\nuser='{$this->user}'\nhost='{$this->host}'\nport={$this->port}\npassword='{$password}'\nprotocol=TCP";
+ file_put_contents($path, $contents);
+ chmod($path, 0600);
+ return $path;
+ }
+
+ protected function getProgramRunnerInstance(): ProgramRunner
+ {
+ return (new ProgramRunner(['mariadb', 'mysql'], '/usr/bin/mysql'));
+ }
+
public function testConnection(): bool
{
- $output = (new ProgramRunner('mysql', '/usr/bin/mysql'))
- ->withEnvironment(['MYSQL_PWD' => $this->password])
- ->withTimeout(300)
- ->withIdleTimeout(300)
- ->runCapturingStdErr([
- '-h', $this->host,
- '-P', $this->port,
- '-u', $this->user,
- '--protocol=TCP',
- $this->database,
- '-e', "show tables;"
- ]);
-
- return !$output;
+ $optionsFile = $this->createOptionsFile();
+
+ try {
+ $stdErr = $this->getProgramRunnerInstance()
+ ->withTimeout(300)
+ ->withIdleTimeout(300)
+ ->runCapturingStdErr([
+ "--defaults-extra-file={$optionsFile}",
+ $this->database,
+ '-e', "show tables;"
+ ]);
+ unlink($optionsFile);
+ } catch (Exception $exception) {
+ unlink($optionsFile);
+ throw $exception;
+ }
+
+ return !$stdErr;
}
public function importSqlFile(string $sqlFilePath): void
{
- $output = (new ProgramRunner('mysql', '/usr/bin/mysql'))
- ->withEnvironment(['MYSQL_PWD' => $this->password])
- ->withTimeout(240)
- ->withIdleTimeout(5)
- ->runCapturingStdErr([
- '-h', $this->host,
- '-P', $this->port,
- '-u', $this->user,
- '--protocol=TCP',
- $this->database,
- '-e', "source {$sqlFilePath}"
- ]);
+ $optionsFile = $this->createOptionsFile();
+
+ try {
+ $output = $this->getProgramRunnerInstance()
+ ->withTimeout(300)
+ ->withIdleTimeout(300)
+ ->runCapturingStdErr([
+ "--defaults-extra-file={$optionsFile}",
+ $this->database,
+ '-e', "source {$sqlFilePath}"
+ ]);
+ unlink($optionsFile);
+ } catch (Exception $exception) {
+ unlink($optionsFile);
+ throw $exception;
+ }
if ($output) {
- throw new Exception("Failed mysql file import with errors:\n" . $output);
+ throw new Exception("Failed mysql file import with errors:\n{$output}");
}
}
$errors = "";
$warnings = "";
$hasOutput = false;
+ $optionsFile = $this->createOptionsFile();
try {
- (new ProgramRunner('mysqldump', '/usr/bin/mysqldump'))
- ->withTimeout(240)
- ->withIdleTimeout(15)
- ->withEnvironment(['MYSQL_PWD' => $this->password])
+ (new ProgramRunner(['mariadb-dump', 'mysqldump'], '/usr/bin/mysqldump'))
+ ->withTimeout(300)
+ ->withIdleTimeout(300)
+ ->withAdditionalPathLocation('C:\xampp\mysql\bin')
->runWithoutOutputCallbacks([
- '-h', $this->host,
- '-P', $this->port,
- '-u', $this->user,
- '--protocol=TCP',
+ "--defaults-extra-file={$optionsFile}",
'--single-transaction',
'--no-tablespaces',
$this->database,
foreach ($lines as $line) {
if (str_starts_with(strtolower($line), 'warning: ')) {
$warnings .= $line;
- } else {
+ } else if (!empty(trim($line))) {
$errors .= $line . "\n";
}
}
});
+ unlink($optionsFile);
} catch (\Exception $exception) {
fclose($file);
+ unlink($optionsFile);
if ($exception instanceof ProcessTimedOutException) {
if (!$hasOutput) {
throw new Exception("mysqldump operation timed-out.\nNo data has been received so the connection to your database may have failed.");
return new static($host, $username, $password, $database, $port);
}
-}
\ No newline at end of file
+}