feat: implement MySQL driver with shell-based import/export and add database transfer UI component
This commit is contained in:
@@ -63,3 +63,8 @@ AWS_BUCKET=
|
|||||||
AWS_USE_PATH_STYLE_ENDPOINT=false
|
AWS_USE_PATH_STYLE_ENDPOINT=false
|
||||||
|
|
||||||
VITE_APP_NAME="${APP_NAME}"
|
VITE_APP_NAME="${APP_NAME}"
|
||||||
|
|
||||||
|
# Database Transfer Tools
|
||||||
|
# Windows example: C:/xampp/mysql/bin/mysqldump.exe
|
||||||
|
MYSQLDUMP_PATH=mysqldump
|
||||||
|
MYSQL_BINARY_PATH=mysql
|
||||||
|
|||||||
@@ -106,6 +106,8 @@ class MySqlDriver implements DatabaseDriverInterface, SchemaDiscoveryInterface
|
|||||||
$path = $directory . DIRECTORY_SEPARATOR . $filename;
|
$path = $directory . DIRECTORY_SEPARATOR . $filename;
|
||||||
$errorPath = $directory . DIRECTORY_SEPARATOR . $filename . '.err';
|
$errorPath = $directory . DIRECTORY_SEPARATOR . $filename . '.err';
|
||||||
|
|
||||||
|
$mysqldumpPath = env('MYSQLDUMP_PATH', 'mysqldump');
|
||||||
|
|
||||||
// Ensure we have a username
|
// Ensure we have a username
|
||||||
$username = $config['username'] ?? 'root';
|
$username = $config['username'] ?? 'root';
|
||||||
$password = $config['password'] ?? '';
|
$password = $config['password'] ?? '';
|
||||||
@@ -117,10 +119,9 @@ class MySqlDriver implements DatabaseDriverInterface, SchemaDiscoveryInterface
|
|||||||
$passwordPart = !empty($password) ? "-p" . escapeshellarg($password) : "";
|
$passwordPart = !empty($password) ? "-p" . escapeshellarg($password) : "";
|
||||||
$dbPart = !empty($database) ? escapeshellarg($database) : "--all-databases";
|
$dbPart = !empty($database) ? escapeshellarg($database) : "--all-databases";
|
||||||
|
|
||||||
// On Windows, we might need to handle double quotes in escapeshellarg
|
|
||||||
// Let's use a more robust way to execute and capture errors
|
|
||||||
$command = sprintf(
|
$command = sprintf(
|
||||||
'mysqldump -u %s %s -h %s -P %s %s > %s 2> %s',
|
'%s -u %s %s -h %s -P %s %s > %s 2> %s',
|
||||||
|
$mysqldumpPath === 'mysqldump' ? 'mysqldump' : escapeshellarg($mysqldumpPath),
|
||||||
escapeshellarg($username),
|
escapeshellarg($username),
|
||||||
$passwordPart,
|
$passwordPart,
|
||||||
escapeshellarg($host),
|
escapeshellarg($host),
|
||||||
@@ -136,15 +137,16 @@ class MySqlDriver implements DatabaseDriverInterface, SchemaDiscoveryInterface
|
|||||||
$errors = file_get_contents($errorPath);
|
$errors = file_get_contents($errorPath);
|
||||||
unlink($errorPath);
|
unlink($errorPath);
|
||||||
if (!empty(trim($errors))) {
|
if (!empty(trim($errors))) {
|
||||||
// If the file is 0 bytes and there are errors, it definitely failed
|
|
||||||
if (!file_exists($path) || filesize($path) === 0) {
|
if (!file_exists($path) || filesize($path) === 0) {
|
||||||
throw new \Exception("Export failed: " . $errors);
|
$instruction = "Please check your .env file and ensure MYSQLDUMP_PATH is correct. Example: MYSQLDUMP_PATH=C:\\xampp\\mysql\\bin\\mysqldump.exe";
|
||||||
|
throw new \Exception("Export failed: " . $errors . "\n\nInstructions: " . $instruction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!file_exists($path) || filesize($path) === 0) {
|
if (!file_exists($path) || filesize($path) === 0) {
|
||||||
throw new \Exception("Export failed: Resulting file is empty. Ensure mysqldump is installed and in the system PATH.");
|
$instruction = "The 'mysqldump' binary was not found. Please set MYSQLDUMP_PATH in your .env file to the absolute path of the mysqldump executable.";
|
||||||
|
throw new \Exception("Export failed: Binary not found.\n\nInstructions: " . $instruction);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $path;
|
return $path;
|
||||||
@@ -157,6 +159,8 @@ class MySqlDriver implements DatabaseDriverInterface, SchemaDiscoveryInterface
|
|||||||
mkdir($directory, 0755, true);
|
mkdir($directory, 0755, true);
|
||||||
}
|
}
|
||||||
$errorPath = $directory . DIRECTORY_SEPARATOR . 'import_error.err';
|
$errorPath = $directory . DIRECTORY_SEPARATOR . 'import_error.err';
|
||||||
|
|
||||||
|
$mysqlPath = env('MYSQL_BINARY_PATH', 'mysql');
|
||||||
|
|
||||||
$username = $config['username'] ?? 'root';
|
$username = $config['username'] ?? 'root';
|
||||||
$password = $config['password'] ?? '';
|
$password = $config['password'] ?? '';
|
||||||
@@ -168,7 +172,8 @@ class MySqlDriver implements DatabaseDriverInterface, SchemaDiscoveryInterface
|
|||||||
$dbPart = !empty($database) ? escapeshellarg($database) : "";
|
$dbPart = !empty($database) ? escapeshellarg($database) : "";
|
||||||
|
|
||||||
$command = sprintf(
|
$command = sprintf(
|
||||||
'mysql -u %s %s -h %s -P %s %s < %s 2> %s',
|
'%s -u %s %s -h %s -P %s %s < %s 2> %s',
|
||||||
|
$mysqlPath === 'mysql' ? 'mysql' : escapeshellarg($mysqlPath),
|
||||||
escapeshellarg($username),
|
escapeshellarg($username),
|
||||||
$passwordPart,
|
$passwordPart,
|
||||||
escapeshellarg($host),
|
escapeshellarg($host),
|
||||||
@@ -184,7 +189,8 @@ class MySqlDriver implements DatabaseDriverInterface, SchemaDiscoveryInterface
|
|||||||
$errors = file_get_contents($errorPath);
|
$errors = file_get_contents($errorPath);
|
||||||
unlink($errorPath);
|
unlink($errorPath);
|
||||||
if (!empty(trim($errors))) {
|
if (!empty(trim($errors))) {
|
||||||
throw new \Exception("Import failed: " . $errors);
|
$instruction = "Please check your .env file and ensure MYSQL_BINARY_PATH is correct. Example: MYSQL_BINARY_PATH=C:\\xampp\\mysql\\bin\\mysql.exe";
|
||||||
|
throw new \Exception("Import failed: " . $errors . "\n\nInstructions: " . $instruction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -98,7 +98,11 @@ const TransferContent: React.FC<TransferContentProps> = ({ mode = 'both' }) => {
|
|||||||
<Close fontSize="small" />
|
<Close fontSize="small" />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
}
|
}
|
||||||
sx={{ borderRadius: 2, boxShadow: '0 4px 12px rgba(0,0,0,0.05)' }}
|
sx={{
|
||||||
|
borderRadius: 2,
|
||||||
|
boxShadow: '0 4px 12px rgba(0,0,0,0.05)',
|
||||||
|
'& .MuiAlert-message': { whiteSpace: 'pre-line' }
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{success || error}
|
{success || error}
|
||||||
</Alert>
|
</Alert>
|
||||||
|
|||||||
Reference in New Issue
Block a user