如何将这个PostgreSQL函数从PL / Py转换为PL / SQL?

时间:2017-02-05 13:35:30

标签: postgresql plpgsql plpython

我有一个用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;

现在对于手头的问题,上面的“黑客”对我有用,但如果我想使用亚马逊的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)

OR

=> SELECT human_readable_bits(5920466906);
 human_readable_bits
---------------------
 5.50 Gb
(1 row)

另外,作为旁注/次要问题,在我创建函数之后,当我查看DDL时,它中有一行显示“SECURITY INVOKER”,是否有人知道这意味着什么?< / p>

1 个答案:

答案 0 :(得分:1)

普通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 表示该函数将使用调用它的用户的权限执行。这是默认值。 SECURITY DEFINER指定该函数将使用创建它的用户的权限执行。