feat: implement dynamic database management via MySQL driver and API controllers
This commit is contained in:
@@ -109,7 +109,7 @@ class SchemaController extends Controller
|
||||
{
|
||||
try {
|
||||
$this->initializeDriver($request);
|
||||
$config = $request->only(['host', 'username', 'password', 'database', 'port']);
|
||||
$config = $request->only(['host', 'username', 'password', 'database', 'port', 'table']);
|
||||
$filePath = $this->databaseService->export($config);
|
||||
|
||||
return Response::download($filePath)->deleteFileAfterSend(true);
|
||||
@@ -154,4 +154,26 @@ class SchemaController extends Controller
|
||||
return Response::json(['error' => $e->getMessage()], 400);
|
||||
}
|
||||
}
|
||||
|
||||
public function tableMetadata(Request $request, $database, $table)
|
||||
{
|
||||
try {
|
||||
$request->merge(['database' => $database]);
|
||||
$this->initializeDriver($request);
|
||||
return Response::json($this->databaseService->getTableMetadata($database, $table));
|
||||
} catch (\Exception $e) {
|
||||
return Response::json(['error' => $e->getMessage()], 400);
|
||||
}
|
||||
}
|
||||
|
||||
public function truncate(Request $request, $table)
|
||||
{
|
||||
try {
|
||||
$this->initializeDriver($request);
|
||||
$this->databaseService->truncateTable($table);
|
||||
return Response::json(['message' => "Table '{$table}' truncated successfully"]);
|
||||
} catch (\Exception $e) {
|
||||
return Response::json(['error' => $e->getMessage()], 400);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,10 +114,16 @@ class MySqlDriver implements DatabaseDriverInterface, SchemaDiscoveryInterface
|
||||
$host = $config['host'] ?? '127.0.0.1';
|
||||
$port = $config['port'] ?? '3306';
|
||||
$database = $config['database'] ?? '';
|
||||
$table = $config['table'] ?? '';
|
||||
|
||||
// Build command with flags for a complete and resilient export
|
||||
$passwordPart = !empty($password) ? "-p" . escapeshellarg($password) : "";
|
||||
$dbPart = !empty($database) ? escapeshellarg($database) : "--all-databases";
|
||||
|
||||
if (!empty($table) && !empty($database)) {
|
||||
$dbPart = escapeshellarg($database) . " " . escapeshellarg($table);
|
||||
} else {
|
||||
$dbPart = !empty($database) ? escapeshellarg($database) : "--all-databases";
|
||||
}
|
||||
|
||||
// --single-transaction: for InnoDB tables, ensures consistency without locking
|
||||
// --skip-lock-tables: avoids issues with views/definers that might prevent locking
|
||||
@@ -225,4 +231,35 @@ class MySqlDriver implements DatabaseDriverInterface, SchemaDiscoveryInterface
|
||||
$results = $this->query($sql, [$database]);
|
||||
return (array) ($results[0] ?? []);
|
||||
}
|
||||
|
||||
public function getTableMetadata(string $database, string $table): array
|
||||
{
|
||||
$sql = "
|
||||
SELECT
|
||||
ENGINE as engine,
|
||||
TABLE_ROWS as rows,
|
||||
DATA_LENGTH as data_length,
|
||||
INDEX_LENGTH as index_length,
|
||||
DATA_FREE as data_free,
|
||||
AUTO_INCREMENT as auto_increment,
|
||||
CREATE_TIME as create_time,
|
||||
UPDATE_TIME as update_time,
|
||||
TABLE_COLLATION as collation,
|
||||
TABLE_COMMENT as comment
|
||||
FROM
|
||||
information_schema.TABLES
|
||||
WHERE
|
||||
TABLE_SCHEMA = ? AND
|
||||
TABLE_NAME = ?
|
||||
";
|
||||
|
||||
$results = $this->query($sql, [$database, $table]);
|
||||
return (array) ($results[0] ?? []);
|
||||
}
|
||||
|
||||
public function truncateTable(string $table): bool
|
||||
{
|
||||
DB::connection($this->connectionName)->statement("TRUNCATE TABLE `{$table}`");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,4 +122,20 @@ class DatabaseService
|
||||
{
|
||||
return $this->getDriver()->getDatabaseMetadata($database);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get table metadata.
|
||||
*/
|
||||
public function getTableMetadata(string $database, string $table): array
|
||||
{
|
||||
return $this->getDriver()->getTableMetadata($database, $table);
|
||||
}
|
||||
|
||||
/**
|
||||
* Truncate a table.
|
||||
*/
|
||||
public function truncateTable(string $table): bool
|
||||
{
|
||||
return $this->getDriver()->truncateTable($table);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,8 @@ Route::prefix('schema')->group(function () {
|
||||
Route::get('/databases', [SchemaController::class, 'databases']);
|
||||
Route::get('/tables/{database}', [SchemaController::class, 'tables']);
|
||||
Route::get('/metadata/{database}', [SchemaController::class, 'metadata']);
|
||||
Route::get('/metadata/{database}/{table}', [SchemaController::class, 'tableMetadata']);
|
||||
Route::post('/truncate/{table}', [SchemaController::class, 'truncate']);
|
||||
Route::get('/{table}', [SchemaController::class, 'schema']);
|
||||
Route::get('/{table}/data', [SchemaController::class, 'data']);
|
||||
Route::post('/execute', [SchemaController::class, 'execute']);
|
||||
|
||||
Reference in New Issue
Block a user