应用场景
很多时候,需要批量对每个模式下的对象进行处理,其中一个办法就是通过登录每个用户去操作对应的模式,这样工作量太大。可以写一个动态执行sql框架,在不切换用户的情况下,以目标用户的环境去执行sql操作,这就需要用到函数(存储过程)的定义者权限。
所谓函数的定义者权限,即以创建函数的用户环境去执行函数。在oracle中,存储过程默认是定义为定义者权限,但是在greenplum中,函数默认是定义为调用者权限(即以调用者的环境执行函数);
动态执行sql
在每个用户对应的schema下面建立 sp_exec 函数
create or replace function sp_exec(character varying)
returns void
language plpgsql
security definer
as $function$
begin
execute $1;
end;
$function$
;
集中调用
通过在gpload用户下建立一个存储过程 sp_execsql 对sp_exec 函数进行管控;
create or replace function sp_execsql(character varying, character varying)
returns void
language plpgsql
as $function$
/* 作者 : v-yuzhenc
* 功能 : 集中处理程序,以某用户的权限执行某条sql语句
* 参数1 : 需要执行的sql语句
* 参数2 : 需要以哪个用户的权限执行该sql语句
* */
declare
p_user varchar := $2;
begin
--临时切换模式搜索路径
execute 'SET search_path TO '||p_user||',public,oracle';
if user in (
'db_dim',
'db_dm',
'db_dwd',
'db_dws',
'db_ods',
'gpload',
'tool',
'sunxiaoyan',
'db_app',
'dataxload')
then
case p_user
when 'db_dim' then perform db_dim.sp_exec($1);
when 'db_dm' then perform db_dm.sp_exec($1);
when 'db_dwd' then perform db_dwd.sp_exec($1);
when 'db_dws' then perform db_dws.sp_exec($1);
when 'db_ods' then perform db_ods.sp_exec($1);
when 'gpload' then perform gpload.sp_exec($1);
when 'gr_screen' then perform gr_screen.sp_exec($1);
else raise exception '未配置该用户:%',p_user;
end case;
else
raise exception '非授权用户:%',user;
end if;
--恢复模式搜索路径
execute 'SET search_path TO '||user||',public,oracle';
exception when others then
--恢复模式搜索路径
execute 'SET search_path TO '||user||',public,oracle';
raise exception '%',sqlerrm;
end;
$function$
;
测试
在普通用户db_ods(或其他用户)下调用gpload.sp_execsql;
select gpload.sp_execsql('drop table tmp','db_dwd');
select gpload.sp_execsql('create table tmp as select 1 id distributed by (id)','db_dwd');
调用gpload.sp_execsql执行动态授权;
select tool.sp_execsql('grant select on table tmp to db_ods','db_dwd');
select * from db_dwd.tmp;