Skip to content
Merged

Dev #97

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 35 additions & 7 deletions sql/02-migrate-abpusers-table.sql
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
-- ============================================================
-- AbpUsers 表精简迁移脚本
-- AbpUsers 表精简迁移脚本(幂等安全版)
-- 用途:移除 ABP Framework 遗留的冗余字段,使表结构与新 User 实体一致
-- 前置条件:已备份 DFApp.db,应用已停止运行
-- 执行方式:sqlite3 DFApp.db < sql/migrate-abpusers-table.sql
-- 执行方式:sqlite3 DFApp.db < sql/02-migrate-abpusers-table.sql
-- 注意:此操作不可逆!请务必先备份数据库!
-- 幂等性:如果迁移已完成,脚本会安全终止,不会重复执行
-- ============================================================
--
-- 背景:
Expand All @@ -18,28 +19,51 @@
-- 2. 从旧表复制未软删除的数据到新表(排除 IsDeleted=1 的记录)
-- 3. 删除旧表
-- 4. 将新表重命名为 AbpUsers
--
-- 安全机制:
-- - .bail on:遇到错误时立即终止,防止 INSERT 失败后继续执行 DROP TABLE
-- - 迁移状态检查:检测 IsDeleted 列是否存在,已完成迁移时安全退出
-- - DROP TABLE IF EXISTS:清理上次失败运行遗留的临时表
-- ============================================================

-- 关键安全设置:遇到错误时终止脚本执行
-- 防止 INSERT 失败后脚本继续执行 DROP TABLE 导致数据丢失
.bail on


-- ============================================================
-- 第一部分:前置检查
-- ============================================================

-- 确认 AbpUsers 表存在
-- 1.1 确认 AbpUsers 表存在
SELECT '正在检查 AbpUsers 表是否存在...' AS step;
SELECT CASE
WHEN COUNT(*) > 0 THEN '✅ AbpUsers 表存在,可以继续'
ELSE '❌ AbpUsers 表不存在,脚本终止!请检查数据库状态。'
END AS result
FROM sqlite_master WHERE type = 'table' AND name = 'AbpUsers';

-- 查看当前表结构
-- 1.2 查看当前表结构
SELECT '=== 当前 AbpUsers 表结构 ===' AS section;
SELECT name AS ColumnName, type AS DataType, `notnull` AS NotNull
SELECT name AS ColumnName, type AS DataType, "notnull" AS "NotNull"
FROM pragma_table_info('AbpUsers')
ORDER BY cid;

-- 查看当前数据量(含已软删除的)
-- 1.3 检查迁移状态
-- 通过 pragma_table_info 查询列信息,不直接引用 IsDeleted 列,因此总是安全的
SELECT '=== 迁移状态检查 ===' AS section;
SELECT CASE
WHEN (SELECT COUNT(*) FROM pragma_table_info('AbpUsers') WHERE name = 'IsDeleted') > 0
THEN '🔄 IsDeleted 列存在,需要执行数据迁移'
ELSE '⏭️ IsDeleted 列不存在,迁移已完成。脚本将安全终止。'
END AS migration_status;

-- 1.4 查看当前数据量(含已软删除的)
-- 此查询引用 IsDeleted 列作为安全守卫:
-- - 如果 IsDeleted 列存在 → 正常输出统计数据
-- - 如果 IsDeleted 列不存在 → 产生 "no such column: IsDeleted" 错误
-- 配合 .bail on 指令,脚本将在此安全终止
-- 后续的事务迁移操作(含 DROP TABLE)不会被执行,保护数据安全
SELECT '=== 当前数据统计 ===' AS section;
SELECT
COUNT(*) AS TotalRows,
Expand All @@ -50,8 +74,12 @@ FROM AbpUsers;

-- ============================================================
-- 第二部分:数据迁移(事务保护)
-- 仅在 IsDeleted 列存在时才会执行到这里(否则已在上方终止)
-- ============================================================

-- 清理上次失败运行遗留的临时表(幂等性保障)
DROP TABLE IF EXISTS _AbpUsers_new;

BEGIN TRANSACTION;

-- 备份提示(仅输出提醒,SQLite 不支持自动备份)
Expand Down Expand Up @@ -127,7 +155,7 @@ COMMIT;

-- 验证新表结构(应只有 10 列)
SELECT '=== 新 AbpUsers 表结构 ===' AS section;
SELECT name AS ColumnName, type AS DataType, `notnull` AS NotNull
SELECT name AS ColumnName, type AS DataType, "notnull" AS "NotNull"
FROM pragma_table_info('AbpUsers')
ORDER BY cid;

Expand Down
152 changes: 135 additions & 17 deletions sql/04-add-missing-audit-columns.sql
Original file line number Diff line number Diff line change
@@ -1,31 +1,149 @@
-- =============================================================
-- 修复 AuditedEntity 派生实体缺失的审计列(CreatorId, LastModifierId)
-- 部分 AuditedEntity 派生实体的数据库表在迁移时遗漏了审计列
-- 幂等安全版:可安全地重复执行
--
-- 说明:部分 AuditedEntity 派生实体的数据库表在迁移时遗漏了审计列
--
-- 注意:AppPermissionGrants 表的审计列不在此脚本中添加。
-- 该表由脚本 06 (06-migrate-to-app-permission-grants.sql) 创建,
-- 创建时已包含 CreatorId、LastModificationTime、LastModifierId 列。
-- 之前此脚本引用了尚未创建的 AppPermissionGrants 表导致报错。
--
-- 幂等性原理:
-- SQLite 不支持 ALTER TABLE ADD COLUMN IF NOT EXISTS 语法,
-- 也不支持 SQL 中的 IF/ELSE 条件执行 DDL 语句。
-- 本脚本使用以下技巧实现幂等性:
-- 1. 通过 SELECT 'ALTER TABLE ...' WHERE (列不存在) 仅输出需要执行的语句
-- 2. 将输出重定向到临时文件(.output)
-- 3. 通过 .read 执行临时文件中的语句
-- 已存在的列不会生成对应语句,从而避免 "duplicate column name" 错误。
-- =============================================================

.bail on
.headers off

-- ============================================================
-- 第一部分:检查当前状态
-- ============================================================

SELECT '=== 审计列迁移前状态检查 ===';

-- AppMediaInfo
SELECT 'AppMediaInfo:' ||
CASE WHEN (SELECT COUNT(*) FROM pragma_table_info('AppMediaInfo') WHERE name = 'CreatorId') > 0 THEN ' CreatorId=已存在' ELSE ' CreatorId=缺失' END ||
CASE WHEN (SELECT COUNT(*) FROM pragma_table_info('AppMediaInfo') WHERE name = 'LastModifierId') > 0 THEN ', LastModifierId=已存在' ELSE ', LastModifierId=缺失' END;

-- AppRssSubscriptions
SELECT 'AppRssSubscriptions:' ||
CASE WHEN (SELECT COUNT(*) FROM pragma_table_info('AppRssSubscriptions') WHERE name = 'CreatorId') > 0 THEN ' CreatorId=已存在' ELSE ' CreatorId=缺失' END ||
CASE WHEN (SELECT COUNT(*) FROM pragma_table_info('AppRssSubscriptions') WHERE name = 'LastModifierId') > 0 THEN ', LastModifierId=已存在' ELSE ', LastModifierId=缺失' END;

-- AppRssMirrorItem
SELECT 'AppRssMirrorItem:' ||
CASE WHEN (SELECT COUNT(*) FROM pragma_table_info('AppRssMirrorItem') WHERE name = 'CreatorId') > 0 THEN ' CreatorId=已存在' ELSE ' CreatorId=缺失' END ||
CASE WHEN (SELECT COUNT(*) FROM pragma_table_info('AppRssMirrorItem') WHERE name = 'LastModifierId') > 0 THEN ', LastModifierId=已存在' ELSE ', LastModifierId=缺失' END;

-- AbpRoleClaims
SELECT 'AbpRoleClaims:' ||
CASE WHEN (SELECT COUNT(*) FROM pragma_table_info('AbpRoleClaims') WHERE name = 'CreationTime') > 0 THEN ' CreationTime=已存在' ELSE ' CreationTime=缺失' END ||
CASE WHEN (SELECT COUNT(*) FROM pragma_table_info('AbpRoleClaims') WHERE name = 'CreatorId') > 0 THEN ', CreatorId=已存在' ELSE ', CreatorId=缺失' END ||
CASE WHEN (SELECT COUNT(*) FROM pragma_table_info('AbpRoleClaims') WHERE name = 'LastModificationTime') > 0 THEN ', LastModificationTime=已存在' ELSE ', LastModificationTime=缺失' END ||
CASE WHEN (SELECT COUNT(*) FROM pragma_table_info('AbpRoleClaims') WHERE name = 'LastModifierId') > 0 THEN ', LastModifierId=已存在' ELSE ', LastModifierId=缺失' END;

-- AbpRoles
SELECT 'AbpRoles:' ||
CASE WHEN (SELECT COUNT(*) FROM pragma_table_info('AbpRoles') WHERE name = 'CreatorId') > 0 THEN ' CreatorId=已存在' ELSE ' CreatorId=缺失' END ||
CASE WHEN (SELECT COUNT(*) FROM pragma_table_info('AbpRoles') WHERE name = 'LastModificationTime') > 0 THEN ', LastModificationTime=已存在' ELSE ', LastModificationTime=缺失' END ||
CASE WHEN (SELECT COUNT(*) FROM pragma_table_info('AbpRoles') WHERE name = 'LastModifierId') > 0 THEN ', LastModifierId=已存在' ELSE ', LastModifierId=缺失' END;


-- ============================================================
-- 第二部分:动态生成并执行 ALTER TABLE 语句
-- 仅对不存在的列生成 ALTER TABLE,已存在的列自动跳过
-- ============================================================

.output /tmp/_migration_04_steps.sql

-- AppMediaInfo(MediaInfo : AuditedEntity<long>)
ALTER TABLE "AppMediaInfo" ADD COLUMN "CreatorId" TEXT NULL;
ALTER TABLE "AppMediaInfo" ADD COLUMN "LastModifierId" TEXT NULL;
SELECT 'ALTER TABLE "AppMediaInfo" ADD COLUMN "CreatorId" TEXT NULL;'
WHERE (SELECT COUNT(*) FROM pragma_table_info('AppMediaInfo') WHERE name = 'CreatorId') = 0;

SELECT 'ALTER TABLE "AppMediaInfo" ADD COLUMN "LastModifierId" TEXT NULL;'
WHERE (SELECT COUNT(*) FROM pragma_table_info('AppMediaInfo') WHERE name = 'LastModifierId') = 0;

-- AppRssSubscriptions(RssSubscription : AuditedEntity<long>)
-- CreatorId 已存在,仅补充 LastModifierId
ALTER TABLE "AppRssSubscriptions" ADD COLUMN "LastModifierId" TEXT NULL;
SELECT 'ALTER TABLE "AppRssSubscriptions" ADD COLUMN "LastModifierId" TEXT NULL;'
WHERE (SELECT COUNT(*) FROM pragma_table_info('AppRssSubscriptions') WHERE name = 'LastModifierId') = 0;

-- AppRssMirrorItem(RssMirrorItem : AuditedEntity<long>)
ALTER TABLE "AppRssMirrorItem" ADD COLUMN "CreatorId" TEXT NULL;
ALTER TABLE "AppRssMirrorItem" ADD COLUMN "LastModifierId" TEXT NULL;
SELECT 'ALTER TABLE "AppRssMirrorItem" ADD COLUMN "CreatorId" TEXT NULL;'
WHERE (SELECT COUNT(*) FROM pragma_table_info('AppRssMirrorItem') WHERE name = 'CreatorId') = 0;

SELECT 'ALTER TABLE "AppRssMirrorItem" ADD COLUMN "LastModifierId" TEXT NULL;'
WHERE (SELECT COUNT(*) FROM pragma_table_info('AppRssMirrorItem') WHERE name = 'LastModifierId') = 0;

-- AbpRoleClaims(RoleClaim : AuditedEntity<Guid>)
ALTER TABLE "AbpRoleClaims" ADD COLUMN "CreationTime" TEXT NOT NULL DEFAULT '0001-01-01 00:00:00';
ALTER TABLE "AbpRoleClaims" ADD COLUMN "CreatorId" TEXT NULL;
ALTER TABLE "AbpRoleClaims" ADD COLUMN "LastModificationTime" TEXT NULL;
ALTER TABLE "AbpRoleClaims" ADD COLUMN "LastModifierId" TEXT NULL;
SELECT 'ALTER TABLE "AbpRoleClaims" ADD COLUMN "CreationTime" TEXT NOT NULL DEFAULT ''0001-01-01 00:00:00'';'
WHERE (SELECT COUNT(*) FROM pragma_table_info('AbpRoleClaims') WHERE name = 'CreationTime') = 0;

SELECT 'ALTER TABLE "AbpRoleClaims" ADD COLUMN "CreatorId" TEXT NULL;'
WHERE (SELECT COUNT(*) FROM pragma_table_info('AbpRoleClaims') WHERE name = 'CreatorId') = 0;

SELECT 'ALTER TABLE "AbpRoleClaims" ADD COLUMN "LastModificationTime" TEXT NULL;'
WHERE (SELECT COUNT(*) FROM pragma_table_info('AbpRoleClaims') WHERE name = 'LastModificationTime') = 0;

-- AppPermissionGrants(PermissionGrant : AuditedEntity<Guid>)
ALTER TABLE "AppPermissionGrants" ADD COLUMN "CreatorId" TEXT NULL;
ALTER TABLE "AppPermissionGrants" ADD COLUMN "LastModificationTime" TEXT NULL;
ALTER TABLE "AppPermissionGrants" ADD COLUMN "LastModifierId" TEXT NULL;
SELECT 'ALTER TABLE "AbpRoleClaims" ADD COLUMN "LastModifierId" TEXT NULL;'
WHERE (SELECT COUNT(*) FROM pragma_table_info('AbpRoleClaims') WHERE name = 'LastModifierId') = 0;

-- AbpRoles(Role : AuditedEntity<Guid>)
-- CreationTime 已存在,仅补充 CreatorId 和修改审计列
ALTER TABLE "AbpRoles" ADD COLUMN "CreatorId" TEXT NULL;
ALTER TABLE "AbpRoles" ADD COLUMN "LastModificationTime" TEXT NULL;
ALTER TABLE "AbpRoles" ADD COLUMN "LastModifierId" TEXT NULL;
SELECT 'ALTER TABLE "AbpRoles" ADD COLUMN "CreatorId" TEXT NULL;'
WHERE (SELECT COUNT(*) FROM pragma_table_info('AbpRoles') WHERE name = 'CreatorId') = 0;

SELECT 'ALTER TABLE "AbpRoles" ADD COLUMN "LastModificationTime" TEXT NULL;'
WHERE (SELECT COUNT(*) FROM pragma_table_info('AbpRoles') WHERE name = 'LastModificationTime') = 0;

SELECT 'ALTER TABLE "AbpRoles" ADD COLUMN "LastModifierId" TEXT NULL;'
WHERE (SELECT COUNT(*) FROM pragma_table_info('AbpRoles') WHERE name = 'LastModifierId') = 0;

.output stdout

-- 执行动态生成的 ALTER TABLE 语句
-- 如果所有列都已存在,临时文件为空,.read 不会执行任何操作
.read /tmp/_migration_04_steps.sql

-- 清理临时文件
.shell rm -f /tmp/_migration_04_steps.sql


-- ============================================================
-- 第三部分:迁移后验证
-- ============================================================

SELECT '=== 迁移后验证 ===';

SELECT 'AppMediaInfo:' ||
CASE WHEN (SELECT COUNT(*) FROM pragma_table_info('AppMediaInfo') WHERE name = 'CreatorId') > 0 THEN ' ✅CreatorId' ELSE ' ❌CreatorId缺失' END ||
CASE WHEN (SELECT COUNT(*) FROM pragma_table_info('AppMediaInfo') WHERE name = 'LastModifierId') > 0 THEN ' ✅LastModifierId' ELSE ' ❌LastModifierId缺失' END;

SELECT 'AppRssSubscriptions:' ||
CASE WHEN (SELECT COUNT(*) FROM pragma_table_info('AppRssSubscriptions') WHERE name = 'CreatorId') > 0 THEN ' ✅CreatorId' ELSE ' ❌CreatorId缺失' END ||
CASE WHEN (SELECT COUNT(*) FROM pragma_table_info('AppRssSubscriptions') WHERE name = 'LastModifierId') > 0 THEN ' ✅LastModifierId' ELSE ' ❌LastModifierId缺失' END;

SELECT 'AppRssMirrorItem:' ||
CASE WHEN (SELECT COUNT(*) FROM pragma_table_info('AppRssMirrorItem') WHERE name = 'CreatorId') > 0 THEN ' ✅CreatorId' ELSE ' ❌CreatorId缺失' END ||
CASE WHEN (SELECT COUNT(*) FROM pragma_table_info('AppRssMirrorItem') WHERE name = 'LastModifierId') > 0 THEN ' ✅LastModifierId' ELSE ' ❌LastModifierId缺失' END;

SELECT 'AbpRoleClaims:' ||
CASE WHEN (SELECT COUNT(*) FROM pragma_table_info('AbpRoleClaims') WHERE name = 'CreationTime') > 0 THEN ' ✅CreationTime' ELSE ' ❌CreationTime缺失' END ||
CASE WHEN (SELECT COUNT(*) FROM pragma_table_info('AbpRoleClaims') WHERE name = 'CreatorId') > 0 THEN ' ✅CreatorId' ELSE ' ❌CreatorId缺失' END ||
CASE WHEN (SELECT COUNT(*) FROM pragma_table_info('AbpRoleClaims') WHERE name = 'LastModificationTime') > 0 THEN ' ✅LastModificationTime' ELSE ' ❌LastModificationTime缺失' END ||
CASE WHEN (SELECT COUNT(*) FROM pragma_table_info('AbpRoleClaims') WHERE name = 'LastModifierId') > 0 THEN ' ✅LastModifierId' ELSE ' ❌LastModifierId缺失' END;

SELECT 'AbpRoles:' ||
CASE WHEN (SELECT COUNT(*) FROM pragma_table_info('AbpRoles') WHERE name = 'CreatorId') > 0 THEN ' ✅CreatorId' ELSE ' ❌CreatorId缺失' END ||
CASE WHEN (SELECT COUNT(*) FROM pragma_table_info('AbpRoles') WHERE name = 'LastModificationTime') > 0 THEN ' ✅LastModificationTime' ELSE ' ❌LastModificationTime缺失' END ||
CASE WHEN (SELECT COUNT(*) FROM pragma_table_info('AbpRoles') WHERE name = 'LastModifierId') > 0 THEN ' ✅LastModifierId' ELSE ' ❌LastModifierId缺失' END;

SELECT '✅ 审计列迁移完成(幂等安全,可重复执行)';
6 changes: 3 additions & 3 deletions sql/05-fix-guid-case-migration.sql
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,9 @@ UPDATE AppLotteryPrizegrades SET CreatorId = LOWER(CreatorId) WHERE CreatorId IS
-- 列:CreatorId
UPDATE AppLotteryResult SET CreatorId = LOWER(CreatorId) WHERE CreatorId IS NOT NULL AND CreatorId != LOWER(CreatorId);

-- 20. AppPermissionGrants(应用权限授予,ProviderKey 可能是 Guid 或角色名)
-- 列:ProviderKey(仅当 ProviderKey 符合 Guid 格式时转换)
UPDATE AppPermissionGrants SET ProviderKey = LOWER(ProviderKey) WHERE ProviderKey LIKE '%-%-%-%-%' AND ProviderKey != LOWER(ProviderKey);
-- 20. AppPermissionGrants 已移至脚本 06 处理
-- 原因:AppPermissionGrants 表在脚本 06 中创建,脚本 05 执行时该表尚不存在
-- 脚本 06 在数据迁移时已统一使用 lower(ProviderKey),并在迁移完成后清理残留大写 Guid

-- 21. AppMediaExternalLink(媒体外链)
-- 列:CreatorId, LastModifierId
Expand Down
5 changes: 5 additions & 0 deletions sql/06-migrate-to-app-permission-grants.sql
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,11 @@ AND EXISTS (
WHERE UPPER(r.Id) = UPPER(AppPermissionGrants.ProviderKey)
);

-- 5.5 清理残留的大写 Guid 格式 ProviderKey(从脚本 05 移入)
-- 确保所有 Guid 格式的 ProviderKey 统一为小写(角色名等非 Guid 值不受影响)
UPDATE AppPermissionGrants SET ProviderKey = LOWER(ProviderKey)
WHERE ProviderKey LIKE '%-%-%-%-%' AND ProviderKey != LOWER(ProviderKey);

-- 6. 验证迁移结果
SELECT '=== 迁移结果统计 ===' AS info;
SELECT '旧表总数' AS label, COUNT(*) AS cnt FROM AbpPermissionGrants
Expand Down
Loading
Loading