-- ===================================================== -- 完整清理脚本 - 解决所有冲突 -- 同时处理触发器、函数、策略冲突 -- ===================================================== -- 第一步:清理触发器 DO $$ BEGIN RAISE NOTICE '🧹 第一步:清理触发器'; -- 删除用户角色相关触发器 DROP TRIGGER IF EXISTS trigger_update_user_roles_updated_at ON public.user_roles CASCADE; DROP TRIGGER IF EXISTS on_auth_user_created ON auth.users CASCADE; -- 删除可能存在的旧版本触发器 DROP TRIGGER IF EXISTS update_user_roles_updated_at ON public.user_roles CASCADE; DROP TRIGGER IF EXISTS handle_new_user_trigger ON auth.users CASCADE; RAISE NOTICE '✅ 触发器清理完成'; END $$; -- 第二步:清理函数(处理参数名称冲突) DO $$ BEGIN RAISE NOTICE '🧹 第二步:清理函数(解决参数冲突)'; -- 删除所有可能冲突的函数(按依赖顺序) DROP FUNCTION IF EXISTS public.batch_update_user_roles(JSONB, UUID) CASCADE; DROP FUNCTION IF EXISTS public.batch_update_user_roles(JSONB) CASCADE; DROP FUNCTION IF EXISTS public.update_user_role(UUID, TEXT, UUID, JSONB) CASCADE; DROP FUNCTION IF EXISTS public.update_user_role(UUID, TEXT, UUID) CASCADE; DROP FUNCTION IF EXISTS public.update_user_role(UUID, TEXT) CASCADE; DROP FUNCTION IF EXISTS public.get_user_role(UUID) CASCADE; DROP FUNCTION IF EXISTS public.get_user_role() CASCADE; DROP FUNCTION IF EXISTS public.sync_user_role_metadata(UUID) CASCADE; DROP FUNCTION IF EXISTS public.user_has_permission(TEXT, UUID) CASCADE; DROP FUNCTION IF EXISTS public.can_access_resource(TEXT, UUID, TEXT, UUID) CASCADE; DROP FUNCTION IF EXISTS public.update_user_roles_updated_at() CASCADE; DROP FUNCTION IF EXISTS public.handle_new_user() CASCADE; DROP FUNCTION IF EXISTS public.test_message_permissions(UUID) CASCADE; DROP FUNCTION IF EXISTS public.test_deployment() CASCADE; RAISE NOTICE '✅ 函数清理完成(解决参数名称冲突)'; END $$; -- 第三步:清理策略 DO $$ DECLARE r RECORD; BEGIN RAISE NOTICE '🧹 第三步:清理策略'; -- 清理 user_roles 表的所有策略 FOR r IN SELECT policyname FROM pg_policies WHERE schemaname = 'public' AND tablename = 'user_roles' LOOP EXECUTE format('DROP POLICY IF EXISTS %I ON public.user_roles', r.policyname); RAISE NOTICE ' 删除策略: %', r.policyname; END LOOP; -- 清理消息相关表的策略 FOR r IN SELECT schemaname, tablename, policyname FROM pg_policies WHERE schemaname = 'public' AND tablename IN ('ak_messages', 'ak_message_recipients', 'ak_message_groups', 'ak_message_group_members', 'ak_message_templates', 'ak_user_message_preferences', 'ak_message_stats', 'ak_message_types') LOOP EXECUTE format('DROP POLICY IF EXISTS %I ON %I.%I', r.policyname, r.schemaname, r.tablename); RAISE NOTICE ' 删除策略: %.%', r.tablename, r.policyname; END LOOP; RAISE NOTICE '✅ 策略清理完成'; END $$; -- 第四步:清理视图(如果存在冲突) DO $$ DECLARE r RECORD; BEGIN RAISE NOTICE '🧹 第四步:清理视图和错误策略'; -- 删除可能错误创建在视图上的策略 FOR r IN SELECT schemaname, tablename, policyname FROM pg_policies WHERE schemaname = 'public' AND tablename IN ( SELECT table_name FROM information_schema.views WHERE table_schema = 'public' ) LOOP BEGIN EXECUTE format('DROP POLICY IF EXISTS %I ON %I.%I', r.policyname, r.schemaname, r.tablename); RAISE NOTICE ' 删除了视图上的错误策略: %.%', r.tablename, r.policyname; EXCEPTION WHEN OTHERS THEN RAISE NOTICE ' 无法删除策略: %.% (这是正常的)', r.tablename, r.policyname; END; END LOOP; -- 重新创建视图 DROP VIEW IF EXISTS public.user_roles_with_email CASCADE; DROP VIEW IF EXISTS public.user_roles_detailed CASCADE; RAISE NOTICE '✅ 视图清理完成'; END $$; -- 第五步:验证清理结果 DO $$ DECLARE trigger_count INTEGER; policy_count INTEGER; function_count INTEGER; BEGIN RAISE NOTICE '🔍 第五步:验证清理结果'; -- 检查触发器 SELECT COUNT(*) INTO trigger_count FROM information_schema.triggers WHERE trigger_schema = 'public' AND trigger_name IN ('trigger_update_user_roles_updated_at', 'on_auth_user_created'); -- 检查策略 SELECT COUNT(*) INTO policy_count FROM pg_policies WHERE schemaname = 'public' AND tablename IN ('user_roles', 'ak_messages', 'ak_message_recipients'); -- 检查核心函数 SELECT COUNT(*) INTO function_count FROM information_schema.routines WHERE routine_schema = 'public' AND routine_name IN ('get_user_role', 'user_has_permission', 'sync_user_role_metadata'); RAISE NOTICE '📊 清理统计:'; RAISE NOTICE ' - 剩余触发器: %', trigger_count; RAISE NOTICE ' - 剩余策略: %', policy_count; RAISE NOTICE ' - 核心函数: %', function_count; IF trigger_count = 0 AND policy_count = 0 THEN RAISE NOTICE '🎉 清理成功!可以安全地重新部署'; ELSE RAISE NOTICE '⚠️ 部分组件仍存在,请检查是否需要进一步清理'; END IF; END $$; -- 第六步:重置RLS状态(确保表可以重新配置策略) DO $$ DECLARE table_record RECORD; BEGIN RAISE NOTICE '🔄 第六步:重置RLS状态'; -- 对所有相关表禁用然后重新启用RLS FOR table_record IN SELECT table_name FROM information_schema.tables WHERE table_schema = 'public' AND table_name IN ('user_roles', 'ak_messages', 'ak_message_recipients', 'ak_message_groups', 'ak_message_group_members', 'ak_message_templates', 'ak_user_message_preferences', 'ak_message_stats', 'ak_message_types') LOOP EXECUTE format('ALTER TABLE public.%I DISABLE ROW LEVEL SECURITY', table_record.table_name); EXECUTE format('ALTER TABLE public.%I ENABLE ROW LEVEL SECURITY', table_record.table_name); RAISE NOTICE ' 重置RLS: %', table_record.table_name; END LOOP; RAISE NOTICE '✅ RLS状态重置完成'; END $$; -- 完成消息 DO $$ BEGIN RAISE NOTICE '🎉 完整清理完成!'; RAISE NOTICE '📋 下一步:'; RAISE NOTICE ' 1. 运行您的主要部署脚本'; RAISE NOTICE ' 2. 验证所有功能正常'; RAISE NOTICE ' 3. 测试权限和角色分配'; END $$; -- 最终状态检查 SELECT '🔧 清理完成' as status, '系统已准备好重新部署' as message, (SELECT COUNT(*) FROM pg_policies WHERE schemaname = 'public') as remaining_policies, (SELECT COUNT(*) FROM information_schema.triggers WHERE trigger_schema = 'public') as remaining_triggers;