如何将此 PostgreSQL 函数从 PL/Py 转换为 PL/SQL?
How to translate this PostgreSQL function from PL/Py to PL/SQL?
我有一个用 PL/Python 编写的函数。它是 运行 在 Python 中的数据库函数,由于通过以下方式安装了过程语言,因此允许该函数:
CREATE PROCEDURAL LANGUAGE 'plpythonu' HANDLER plpython_call_handler
(我发现了一个很好的技巧,通过使用唯一的名称允许非管理员用户访问 运行,虽然这与我的问题没有太大关系,但我相信你们中的一些人会想知道我是怎么做到的,所以下面是答案)
CREATE TRUSTED PROCEDURAL LANGUAGE 'plpythonu2' HANDLER plpython_call_handler
GRANT USAGE ON LANGUAGE plpythonu2 TO admin;
现在问题来了,我上面的"hack"对我有用,但是如果我想使用亚马逊的RDS服务,我无法安装语言,PL/Python也不可用。 SQL 然而,是。
因此,我需要帮助将 Python 中编写的以下函数翻译成纯 SQL。
CREATE OR REPLACE FUNCTION "public"."human_readable_bits" (
"b" bigint = 0
)
RETURNS varchar AS
$body$
import math
if b:
exponent = math.floor(math.log(b)/math.log(1024))
val = b/pow(1024, math.floor(exponent))
val = round(val*2)/2 -- This rounds to the nearest HALF (X.5) B, Kb, Mb, Gb, etc.
return "%.2f %s" % (val, ('B','Kb','Mb','Gb','Tb','Pb','Eb','Zb','Yb')[int(exponent)])
else:
return "0 Gb"
$body$
LANGUAGE 'plpythonu2'
VOLATILE
RETURNS NULL ON NULL INPUT
SECURITY INVOKER
COST 100;
此函数允许我执行如下查询:
=> SELECT human_readable_bits(3285824466906);
human_readable_bits
---------------------
3.00 Tb
(1 row)
或
=> SELECT human_readable_bits(5920466906);
human_readable_bits
---------------------
5.50 Gb
(1 row)
此外,作为一个 side-note/secondary 问题,在我创建函数之后,当我查看 DDL 时,其中有一行内容是 "SECURITY INVOKER," 有人知道那是什么吗 means/does?
普通 PLPGSQL 函数的转换为:
CREATE OR REPLACE FUNCTION public.human_readable_bits(b NUMERIC)
RETURNS VARCHAR AS
$BODY$
declare
exponent integer;
val float;
arr varchar[];
sz VARCHAR(10);
result varchar(20);
BEGIN
if b is null or b = 0 then
return '0 B';
end if;
if b < 1024 then
return b::varchar || ' Bits';
end if;
arr := ARRAY['B','Kb','Mb','Gb','Tb','Pb','Eb','Zb','Yb'];
exponent := floor( log(b) / log(1024));
val := b/power(1024,exponent);
val := round(val*2)/2;
sz := arr[trunc(floor(log(b) / log(1024)))];
if strpos(val::varchar,'.') > 0 then
result := substr(val::varchar, 1, strpos(val::varchar,'.')-1);
result := result || '.' || rpad( substr(val::varchar, strpos(val::varchar,'.')+1), 2, '0' ) || ' ' || sz;
else
result := val::varchar || '.00 ' || sz;
end if;
return result;
END;
$BODY$
LANGUAGE plpgsql VOLATILE;
作为这个函数的结果:
select human_readable_bits(328582446690656456434534453) hrb0,
human_readable_bits(3285824466906) hrb1,
human_readable_bits(5920466906) hrb2,
human_readable_bits(1024) hrb3,
human_readable_bits(512) hrb4,
human_readable_bits(null) hrb5;
会导致:
hrb0 hrb1 hrb2 hrb3 hrb4 hrb5
272.00 Zb 3.00 Gb 5.50 Mb 1.00 B 512 Bits 0 B
根据您的问题,答案很容易在 Create Function Documentation
中找到
SECURITY INVOKER indicates that the function is to be executed with the privileges of the user that calls it. That is the default. SECURITY DEFINER specifies that the function is to be executed with the privileges of the user that created it.
我有一个用 PL/Python 编写的函数。它是 运行 在 Python 中的数据库函数,由于通过以下方式安装了过程语言,因此允许该函数:
CREATE PROCEDURAL LANGUAGE 'plpythonu' HANDLER plpython_call_handler
(我发现了一个很好的技巧,通过使用唯一的名称允许非管理员用户访问 运行,虽然这与我的问题没有太大关系,但我相信你们中的一些人会想知道我是怎么做到的,所以下面是答案)
CREATE TRUSTED PROCEDURAL LANGUAGE 'plpythonu2' HANDLER plpython_call_handler
GRANT USAGE ON LANGUAGE plpythonu2 TO admin;
现在问题来了,我上面的"hack"对我有用,但是如果我想使用亚马逊的RDS服务,我无法安装语言,PL/Python也不可用。 SQL 然而,是。
因此,我需要帮助将 Python 中编写的以下函数翻译成纯 SQL。
CREATE OR REPLACE FUNCTION "public"."human_readable_bits" (
"b" bigint = 0
)
RETURNS varchar AS
$body$
import math
if b:
exponent = math.floor(math.log(b)/math.log(1024))
val = b/pow(1024, math.floor(exponent))
val = round(val*2)/2 -- This rounds to the nearest HALF (X.5) B, Kb, Mb, Gb, etc.
return "%.2f %s" % (val, ('B','Kb','Mb','Gb','Tb','Pb','Eb','Zb','Yb')[int(exponent)])
else:
return "0 Gb"
$body$
LANGUAGE 'plpythonu2'
VOLATILE
RETURNS NULL ON NULL INPUT
SECURITY INVOKER
COST 100;
此函数允许我执行如下查询:
=> SELECT human_readable_bits(3285824466906);
human_readable_bits
---------------------
3.00 Tb
(1 row)
或
=> SELECT human_readable_bits(5920466906);
human_readable_bits
---------------------
5.50 Gb
(1 row)
此外,作为一个 side-note/secondary 问题,在我创建函数之后,当我查看 DDL 时,其中有一行内容是 "SECURITY INVOKER," 有人知道那是什么吗 means/does?
普通 PLPGSQL 函数的转换为:
CREATE OR REPLACE FUNCTION public.human_readable_bits(b NUMERIC)
RETURNS VARCHAR AS
$BODY$
declare
exponent integer;
val float;
arr varchar[];
sz VARCHAR(10);
result varchar(20);
BEGIN
if b is null or b = 0 then
return '0 B';
end if;
if b < 1024 then
return b::varchar || ' Bits';
end if;
arr := ARRAY['B','Kb','Mb','Gb','Tb','Pb','Eb','Zb','Yb'];
exponent := floor( log(b) / log(1024));
val := b/power(1024,exponent);
val := round(val*2)/2;
sz := arr[trunc(floor(log(b) / log(1024)))];
if strpos(val::varchar,'.') > 0 then
result := substr(val::varchar, 1, strpos(val::varchar,'.')-1);
result := result || '.' || rpad( substr(val::varchar, strpos(val::varchar,'.')+1), 2, '0' ) || ' ' || sz;
else
result := val::varchar || '.00 ' || sz;
end if;
return result;
END;
$BODY$
LANGUAGE plpgsql VOLATILE;
作为这个函数的结果:
select human_readable_bits(328582446690656456434534453) hrb0,
human_readable_bits(3285824466906) hrb1,
human_readable_bits(5920466906) hrb2,
human_readable_bits(1024) hrb3,
human_readable_bits(512) hrb4,
human_readable_bits(null) hrb5;
会导致:
hrb0 hrb1 hrb2 hrb3 hrb4 hrb5
272.00 Zb 3.00 Gb 5.50 Mb 1.00 B 512 Bits 0 B
根据您的问题,答案很容易在 Create Function Documentation
中找到SECURITY INVOKER indicates that the function is to be executed with the privileges of the user that calls it. That is the default. SECURITY DEFINER specifies that the function is to be executed with the privileges of the user that created it.