ThinkAdmin/plugin/think-plugs-system/tests/helper/DatabaseMaintenanceTest.php
邹景立 ea10f17079 feat(database): 适配多数据库维护操作
新增 DatabaseMaintenance 适配器,按数据库类型生成维护语句:MySQL/MariaDB 支持 REPAIR 与 OPTIMIZE,SQLite 使用 PRAGMA optimize 与 VACUUM,PostgreSQL 使用 VACUUM ANALYZE,SQL Server 使用索引重组与统计信息更新。

重构 DatabaseCommand,将 repair 与 optimize 统一收敛到维护适配器执行,针对不支持的数据库返回友好队列成功提示,避免 SQLite 等环境直接报错中断任务。

补充 DatabaseMaintenanceTest 覆盖各数据库语句生成、标识符转义和不支持提示,并将测试加入 phpunit.xml.dist 的套件列表。
2026-05-21 00:17:24 +08:00

119 lines
5.7 KiB
PHP

<?php
declare(strict_types=1);
/**
* +----------------------------------------------------------------------
* | ThinkAdmin Plugin
* +----------------------------------------------------------------------
* | Copyright (c) 2014~2026 ThinkAdmin [ thinkadmin.top ]
* +----------------------------------------------------------------------
* | Official Website: https://thinkadmin.top
* +----------------------------------------------------------------------
* | Licensed: https://mit-license.org
* | Disclaimer: https://thinkadmin.top/disclaimer
* | Vip Rights: https://thinkadmin.top/vip-introduce
* +----------------------------------------------------------------------
* | Gitee Repository: https://gitee.com/zoujingli/ThinkAdmin
* | Github Repository: https://github.com/zoujingli/ThinkAdmin
* +----------------------------------------------------------------------
*/
namespace plugin\system\tests\helper;
use PHPUnit\Framework\TestCase;
use plugin\system\helper\command\database\DatabaseMaintenance;
/**
* @internal
* @coversNothing
*/
class DatabaseMaintenanceTest extends TestCase
{
public function testMysqlBuildsOptimizeAndRepairStatements(): void
{
$adapter = new DatabaseMaintenance('mysql');
$this->assertTrue($adapter->supports(DatabaseMaintenance::ACTION_OPTIMIZE));
$this->assertTrue($adapter->supports(DatabaseMaintenance::ACTION_REPAIR));
$this->assertTrue($adapter->requiresTables(DatabaseMaintenance::ACTION_OPTIMIZE));
$optimize = $adapter->operations(DatabaseMaintenance::ACTION_OPTIMIZE, [
'system_queue',
'admin.system_user',
'weird`name',
]);
$repair = $adapter->operations(DatabaseMaintenance::ACTION_REPAIR, ['system_queue']);
$this->assertSame('OPTIMIZE TABLE `system_queue`', $optimize[0]['statements'][0]['sql']);
$this->assertSame('OPTIMIZE TABLE `admin`.`system_user`', $optimize[1]['statements'][0]['sql']);
$this->assertSame('OPTIMIZE TABLE `weird``name`', $optimize[2]['statements'][0]['sql']);
$this->assertSame(DatabaseMaintenance::MODE_QUERY, $optimize[0]['statements'][0]['mode']);
$this->assertSame('REPAIR TABLE `system_queue`', $repair[0]['statements'][0]['sql']);
}
public function testSqliteBuildsDatabaseScopedOptimizeAndSkipsRepair(): void
{
$adapter = new DatabaseMaintenance('sqlite');
$this->assertTrue($adapter->supports(DatabaseMaintenance::ACTION_OPTIMIZE));
$this->assertFalse($adapter->supports(DatabaseMaintenance::ACTION_REPAIR));
$this->assertFalse($adapter->requiresTables(DatabaseMaintenance::ACTION_OPTIMIZE));
$operations = $adapter->operations(DatabaseMaintenance::ACTION_OPTIMIZE, ['system_queue']);
$this->assertSame('数据库', $operations[0]['target']);
$this->assertSame('PRAGMA optimize', $operations[0]['statements'][0]['sql']);
$this->assertSame('VACUUM', $operations[0]['statements'][1]['sql']);
$this->assertSame(DatabaseMaintenance::MODE_EXECUTE, $operations[0]['statements'][0]['mode']);
$this->assertSame([], $adapter->operations(DatabaseMaintenance::ACTION_REPAIR, ['system_queue']));
$this->assertSame('SQLITE 数据库暂不支持 REPAIR 操作,已跳过处理。', $adapter->unsupportedMessage(DatabaseMaintenance::ACTION_REPAIR));
}
public function testPgsqlBuildsVacuumAnalyzeWithDoubleQuotedTables(): void
{
$adapter = new DatabaseMaintenance('postgresql');
$this->assertTrue($adapter->supports(DatabaseMaintenance::ACTION_OPTIMIZE));
$this->assertFalse($adapter->supports(DatabaseMaintenance::ACTION_REPAIR));
$this->assertTrue($adapter->requiresTables(DatabaseMaintenance::ACTION_OPTIMIZE));
$operations = $adapter->operations(DatabaseMaintenance::ACTION_OPTIMIZE, [
'public.system_queue',
'weird"name',
]);
$this->assertSame('VACUUM (ANALYZE) "public"."system_queue"', $operations[0]['statements'][0]['sql']);
$this->assertSame('VACUUM (ANALYZE) "weird""name"', $operations[1]['statements'][0]['sql']);
$this->assertSame(DatabaseMaintenance::MODE_EXECUTE, $operations[0]['statements'][0]['mode']);
}
public function testSqlsrvBuildsIndexAndStatisticsStatementsWithBracketQuotedTables(): void
{
$adapter = new DatabaseMaintenance('mssql');
$this->assertTrue($adapter->supports(DatabaseMaintenance::ACTION_OPTIMIZE));
$this->assertFalse($adapter->supports(DatabaseMaintenance::ACTION_REPAIR));
$this->assertTrue($adapter->requiresTables(DatabaseMaintenance::ACTION_OPTIMIZE));
$operations = $adapter->operations(DatabaseMaintenance::ACTION_OPTIMIZE, [
'dbo.system_queue',
'weird]name',
]);
$this->assertSame('ALTER INDEX ALL ON [dbo].[system_queue] REORGANIZE', $operations[0]['statements'][0]['sql']);
$this->assertSame('UPDATE STATISTICS [dbo].[system_queue]', $operations[0]['statements'][1]['sql']);
$this->assertSame('ALTER INDEX ALL ON [weird]]name] REORGANIZE', $operations[1]['statements'][0]['sql']);
$this->assertSame(DatabaseMaintenance::MODE_EXECUTE, $operations[0]['statements'][0]['mode']);
}
public function testUnsupportedDatabaseReturnsNoOperations(): void
{
$adapter = new DatabaseMaintenance('oracle');
$this->assertFalse($adapter->supports(DatabaseMaintenance::ACTION_OPTIMIZE));
$this->assertFalse($adapter->supports(DatabaseMaintenance::ACTION_REPAIR));
$this->assertSame([], $adapter->operations(DatabaseMaintenance::ACTION_OPTIMIZE, ['system_queue']));
$this->assertSame('ORACLE 数据库暂不支持 OPTIMIZE 操作,已跳过处理。', $adapter->unsupportedMessage(DatabaseMaintenance::ACTION_OPTIMIZE));
}
}