返回首页

gbase数据、南大通用产品文档:GBase8a脱敏规则

更新日期:2024年09月11日

函数按照不同的处理逻辑,脱敏规则的获取方式也不相同,大致可分为两类。
1.
控制流函数可以直接返回脱敏列,而非对脱敏列进行比较和计算,这时函数会
将脱敏列的脱敏规则应用到其他返回值。这类函数有case when/decode、if、
ifnull、nvl 和coalesce 函数。举例如下:
select case col when 1 then '123' when 2 then '456' when 3 then mask_col else '789' end from t;
说明
其中col 为非脱敏列,mask_col 为脱敏列,“123”、“456”、“789” 为常量。
上面查询中case when 函数可能的返回值为’123’、’456’、’789’和mask_col,返
回值中包含了脱敏列,这时会对常量’123’、’456’和’789’按照脱敏列mask_col
的脱敏规则进行脱敏。

当这类函数的返回值中有多个脱敏列(不同列)时,该函数将使用默认脱敏规
则(不考虑多列脱敏规则是否完全相同)。
比如:
select nvl(mask_col1, mask_col2) from t;
nvl 函数将使用默认脱敏规则。

select nvl(mask_col1, mask_col1) from t;
nvl 函数仍将使用mask_col1 的脱敏规则。

当这类函数的返回值中既包含脱敏列,同时也包含非脱敏列(不是常量)时,
该函数也将使用默认脱敏规则。
比如:
select coalesce(col, mask_col) from t;
coalesce 函数将使用默认脱敏规则。

当这类函数的返回值中类型不完全相同时,
将会依据数据类型的转换规则进行

GBase 8a MPP Cluster 产品手册
4 管理员指南
文档版本953(2022-09-15)
南大通用数据技术股份有限公司
465
转换,
如果转换后的数据类型与脱敏列的原始类型不一致
(只考虑string、
real、
decimal 和int 四个级别,而不考虑更细的数据类型),则使用默认脱敏。
比如:
select coalesce(mask_int_col, 'abcdef') from t;
coalesce 函数返回值为string,
与mask_int_col 的类型(int)不一致,
所以coalesce
将使用默认脱敏。
默认脱敏时,
并不是将mask_int_col 的值转换为string,
而是直接返回string 类
型的默认脱敏值(xxxx)。
控制流函数类型转换规则:

任何一个参数为string 时,则按string 进行运算;

没有string 时,如果存在real,按real 进行运算;

没有string 和real 时,如果存在decimal,按decimal 进行运算;

日期时间类型算作string 类型。
控制流函数只对所有可能的返回值进行脱敏,对控制逻辑中的其他参数不脱
敏,比如case when 函数中只对then 和else 进行脱敏,对case 和when 分支中
的参数不脱敏。

Union、
Intersect 和Minus 运算时,
对应列的脱敏规则选取与控制流函数的脱敏
规则一致。
比如:
select mask_int_col from t union select mask_int_col as col from t;
将使用mask_int_col 的脱敏规则,而:
select mask_int_col from t union select mask_int_col+1 from t;
将使用默认脱敏。
2.
绝大部分函数是对参数进行比较或者计算,比如一些字符串函数、比较函数、
数值函数、时间和日期函数、OLAP 函数和聚集函数等,这类函数的参数如果
有脱敏列,函数将使用默认脱敏规则对返回值进行脱敏,而非对脱敏列脱敏后
参与运算。
举例如下:
select concat(mask_col, '123') from t;
其中mask_col 为脱敏列,’123’为常量。
上面查询中concat 函数并非将脱敏后的mask_col 字符串连接常量’123’,而是
对concat 返回值进行默认脱敏。
由于concat 返回值是字符类型,
所以上述结果
除mask_col 为NULL 的情况外(NULL 值情况返回值为NULL),始终返

GBase 8a MPP Cluster 产品手册
4 管理员指南
文档版本953(2022-09-15)
南大通用数据技术股份有限公司
466
回’xxxx’。
再比如select mask_col > 1 from t; 将依据函数“>”的返回值类型使用默认脱
敏规则,所以除mask_col 为NULL 值外,始终返回0。
脱敏列脱敏后如果超过脱敏列的最大长度,则自动截断为脱敏列的最大长度。
比如脱敏列定义为:
mask_col varchar(5) masked with (function ='partial(2,"xxxx",2)')
则值“abcde”理论上应脱敏为“abxxxxde”,脱敏后的长度超过了最大长度5,
自动截断为“abxxx”。
同样,对于一些可设置长度的函数脱敏时也会被截断,比如:
select left(mask_col, 2) from t;
left 函数将使用默认脱敏,理论上应脱敏为“xxxx”,但超过了left 函数设置
的最大长度,所以自动截断为“xx”。

命名的行的 Java™ 类必须实现 SQLData 接口。对于命名的行中每一元素,该类必须有一
个成员,但除了这些之外可有其他成员。这些成员可以按任何顺序,且不要公开。

GBase 8s JDBC Driver 程序员指南
南大通用数据技术股份有限公司
- 123 -

对于命名的行,Java 类必须实现 writeSQL()、readSQL() 和 getSQLTypeName() 方法,如
在 SQLData 接口中定义的那样,但可实现附加的方法。可使用 ClassGenerator 实用程序来
创建该类;要获取更多信息,请参阅 ClassGenerator 实用程序。
要以命名的行来链接此 Java 类,请使用 Connection.setTypeMap() 方法或 getObject() 方法,
来创建定制的类型映射。要获取关于类型映射的更多信息,请参阅 映射数据类型。
不可使用 SQLData 接口来访问未命名的行。
SQLData 示例
本部分中所有示例的完整版本位于安装了驱动程序处的 demo/complex-types 目录中。要获
取更多信息,请参阅 示例代码文件。
下列示例包括一个实现 java.sql.SQLData 接口的 Java™ 类。
这里是样例数据库模式:
CREATE ROW TYPE fullname_t (first char(20), last char(20));
CREATE ROW TYPE person_t (id int, name fullname_t, age int);
CREATE TABLE teachers (person person_t, dept char (20));
INSERT INTO teachers VALUES ("row(100, row('Bill', 'Smith'), 27)", "physics");
这是 fullname Java 类:
import java.sql.*;
public class fullname implements SQLData
{
public String first;
public String last;
private String sql_type = "fullname_t";

public String getSQLTypeName()
{
return sql_type;
}
public void readSQL (SQLInput stream, String type) throws
SQLException
{
sql_type = type;
first = stream.readString();
last = stream.readString();
}
public void writeSQL (SQLOutput stream) throws SQLException

GBase 8s JDBC Driver 程序员指南
南大通用数据技术股份有限公司
- 124 -

{
stream.writeString(first);
stream.writeString(last);
}
/*
* Function not required by SQLData interface, but makes
* it easier for displaying results.
*/
public String toString()
{
String s = "fullname: ";
s += "first: " + first + " last: " + last;
return s;
}
}
这是 person Java 类:
import java.sql.*;
public class person implements SQLData
{
public int id;
public fullname name;
public int age;
private String sql_type = "person_t";

public String getSQLTypeName()
{
return sql_type;
}
public void readSQL (SQLInput stream, String type) throws SQLException
{
sql_type = type;
id = stream.readInt();
name = (fullname)stream.readObject();
age = stream.readInt();
}
public void writeSQL (SQLOutput stream) throws SQLException
{

GBase 8s JDBC Driver 程序员指南
南大通用数据技术股份有限公司
- 125 -

stream.writeInt(id);
stream.writeObject(name);
stream.writeInt(age);
}
public String toString()
{
String s = "person:";
s += "id: " + id + "\n";
s += " name: " + name.toString() + "\n";
s += " age: " + age + "\n";
return s;
}
}
这里是访存命名的行的示例:
java.util.Map map = conn.getTypeMap();
conn.setTypeMap(map);
map.put("fullname_t", Class.forName("fullname"));
map.put("person_t", Class.forName("person"));

...
PreparedStatement pstmt;
ResultSet rs;
pstmt = conn.prepareStatement("select person from teachers");
System.out.println("prepare ...ok");

rs = pstmt.executeQuery();
System.out.println("executetQuery()...ok");

while (rs.next())
{
person who = (person) rs.getObject(1);
System.out.println("getObject()...ok");
System.out.println("Data fetched:");
System.out.println("row: " + who.toString());
}
pstmt.close();

GBase 8s JDBC Driver 程序员指南
南大通用数据技术股份有限公司
- 126 -

通过 Connection 对象,conn.getTypeMap() 方法从 java.util.Map 对象返回命名的行映射信
息。
map.put() 方法注册数据库服务器上嵌套的命名的行 fullname_t 与 Java 类 fullname 之间
的映射,以及数据库服务器上命名的行 person_t 与 Java 类 person 之间的映射。
person who = (person) rs.getObject(1) 语句将命名的行检索至 Java 对象 who 内。GBase 8s
JDBC Driver 承认此对象 who 是命名的行、distinct 类型或 opaque 类型,因为数据库服务
器发送的信息有扩展的名称 person_t。
驱动程序查找 person_t,
并发现它是命名的行。
驱动程序以键 person_t 调用 map.get() 方法,
其返回 person 类对象。实例化类 person 的一个对象。
person 类中的 readSQL() 方法调用定义在 SQLInput 接口中的方法,来将 ROW 列中每一
字段转换为 Java 对象,并将每一指定为 person 类中的一个成员。
下列展示一个方法,用于使用 setObject() 方法将 Java 对象插入至命名的行列内:
java.util.Map map = conn.getTypeMap();
map.put("fullname_t", Class.forName("fullname"));
map.put("person_t", Class.forName("person"));

...
PreparedStatement pstmt;
System.out.println("Populate person and fullname objects");
person who = new person();
fullname name = new fullname();
name.last = "Jones";
name.first = "Sarah";
who.id = 567;
who.name = name;
who.age = 17;

String s = "insert into teachers values (?, 'physics')";
pstmt = conn.prepareStatement (s);
System.out.println("prepared...ok");

pstmt.setObject(1, who);
System.out.println("setObject()...ok");

int rowcount = pstmt.executeUpdate();
System.out.println("executeUpdate()...ok");
pstmt.close();

GBase 8s JDBC Driver 程序员指南
南大通用数据技术股份有限公司
- 127 -

通过 Connection 对象,conn.getTypeMap() 方法从 java.util.Map 对象返回命名的行映射信
息。
map.put() 方法注册数据库服务器上嵌套的命名的行 fullname_t 与 Java 类 fullname 之间
的映射,以及数据库服务器上命名的行 person_t 与 Java 类 person 之间的映射。
GBase 8s JDBC Driver 认可对象 who 实现 SQLData 接口,
因此,
它是命名的行、
distinct 类
型,
或 opaque 类型。
对于此对象,
GBase 8s JDBC Driver 调用 getSQLTypeName() 方法
(需
要类实现 SQLData 接口),其返回 person_t。驱动程序查找 person_t,并发现它是命名的
行。
对于类中的每一成员,
person 类中的 writeSQL() 方法调用对应的 SQLOutput.writeXXX() 方
法,将其每一都映射至命名的行 person_t 中的一个字段。该类中的 writeSQL() 方法包含
对 SQLOutput.writeObject(name) 和 SQLOutput.writeInt(id) 方法的调用。序列化类 person 的
每一成员,并写至流内。

函数说明
返回逆序输出的字符串。
示例
示例1:将“abc”按从右到左的顺序输出。
gbase> SELECT REVERSE('abc') FROM dual;
+----------------+
| REVERSE('abc') |
+----------------+
| cba
|
+----------------+
1 row in set