
# 密态支持函数/存储过程
密态支持函数/存储过程，当前版本只支持sql和plpgsql两种语言。由于密态支持存储过程中创建和执行函数/存储过程对用户是无感知的，因此语法和非密态无区别。
函数/存储过程语法参考[用户自定义函数](https://support.huaweicloud.com/distributed-devg-v10-gaussdb/gaussdb-12-0348.html)章节和《参考》中"存储过程"章节。
密态等值查询支持函数存储过程新增系统表gs_encrypted_proc，用于存储参数返回的原始数据类型。
系统表具体字段含义可参考《参考》中"系统表和系统视图 \> 系统表 \> 密态等值查询 \> GS_ENCRYPTED_PROC"章节。
#### 创建并执行涉及加密列的函数/存储过程
1. 创建密钥，详细步骤请参见[使用gsql操作密态数据库](https://support.huaweicloud.com/distributed-devg-v10-gaussdb/gaussdb-12-0376.html)。
2. 创建加密表。 
   ```
   gaussdb=# CREATE TABLE creditcard_info (
      id_number int,
      name  text,
      credit_card varchar(19) encrypted with (column_encryption_key = cek1, encryption_type = DETERMINISTIC)
    ) with (orientation=row) distribute by hash(id_number);
   CREATE TABLE
   ```
   
   
3. 插入数据。 
   ```
   gaussdb=# insert into creditcard_info values(1, 'Avi', '1234567890123456');
   INSERT 0 1
   gaussdb=# insert into creditcard_info values(2, 'Eli', '2345678901234567');
   INSERT 0 1
   ```
   
   
4. 创建函数支持密态等值查询。 
   ```
   gaussdb=# CREATE FUNCTION f_encrypt_in_sql(val1 text, val2 varchar(19)) RETURNS text AS 'SELECT name from creditcard_info where name=$1 or credit_card=$2 LIMIT 1' LANGUAGE SQL;
   CREATE FUNCTION
   gaussdb=# CREATE FUNCTION f_encrypt_in_plpgsql (val1 text, val2 varchar(19), OUT c text) AS $$
    BEGIN
    SELECT into c name from creditcard_info where name=$1 or credit_card =$2 LIMIT 1;
    END; $$
    LANGUAGE plpgsql;
   CREATE FUNCTION
   ```
   
   
5. 执行函数。 
   ```
   gaussdb=# SELECT f_encrypt_in_sql('Avi','1234567890123456');
    f_encrypt_in_sql
   ------------------
    Avi
   (1 row)
   gaussdb=# SELECT f_encrypt_in_plpgsql('Avi', val2=>'1234567890123456');
    f_encrypt_in_plpgsql
   ----------------------
    Avi
   (1 row)
   ```
   
   
 
![](https://support.huaweicloud.com/distributed-devg-v10-gaussdb/public_sys-resources/note_3.0-zh-cn.png)
1. 函数/存储过程中的"执行动态查询语句"所包含的查询是在执行过程编译，因此函数/存储过程中的表名、列名不能在创建阶段未知，输入参数不能用于表名、列名或以任何方式连接。
2. 函数/存储过程中的"执行动态查询语句"不支持EXECUTE 'query'中带有需要加密的数据值。
3. 函数不支持RETURN QUERY EXECUTE 'query'动态查询语句实际返回数据为密态类型，而函数声明返回值为明文类型的场景。
4. 在RETURNS、IN和OUT的参数中，不支持混合使用加密和非加密类型参数。虽然参数类型都是原始数据类型，但实际类型不同。
5. 在高级包接口中，如dbe_output.print_line()等在服务端打印输出的接口不会做解密操作，是由于加密数据类型在强转成明文原始数据类型时会打印出该数据类型的默认值。
6. 当前版本函数/存储过程的LANGUAGE只支持SQL和plpgsql，不支持C和JAVA等其他过程语言。
7. 不支持在函数/存储过程中执行其他查询加密列的函数/存储过程。
8. 当前版本不支持default、DECLARE中为变量授予默认值，且不支持对DECLARE中的返回值进行解密，且不支持介于 IS/AS 与 BEGIN 之间的声明部分进行解密操作，用户可以在执行函数时用输入参数、输出参数来代替使用。
9. 不支持gs_dump对涉及加密列的function进行备份后再恢复操作。
10. 不支持在函数/存储过程中创建密钥。
11. 密态函数/存储过程不支持触发器。
12. 密态等值查询函数/存储过程不支持对plpgsql语言对语法进行转义，对于语法主体带有引号的CREATE FUNCTION AS '语法主体'，可以用CREATE FUNCTION AS $$语法主体$$代替。
13. 不支持在密态等值查询函数/存储过程中执行修改加密列定义的操作后立即使用该加密列进行加密处理，例如，存储过程中创建的加密表，添加加密列，向表中插入数据等组合操作无法支持，由于执行函数/存储过程是在服务端，客户端没法判断是否需要刷新缓存，需断开连接后或触发刷新客户端加密列缓存才可以对该列做加密操作。
14. 不支持使用密态数据类型（byteawithoutorderwithequalcol、byteawithoutordercol、_byteawithoutorderwithequalcol、_byteawithoutordercol）创建函数和存储过程。
15. 密态函数若返回值有加密类型，不支持返回不确定的行类型结果，如RETURN \[SETOF\] RECORD，可以使用返回可确定的行类型结果替代，如RETURN TABLE(columnname typename\[,...\])。
16. 密态支持函数在创建加密函数时会在系统表gs_encrypted_proc中添加参数对应的加密列的OID，因此删除表后重建同名表可能会使密态函数失效，需要重新创建密态函数。
 
