plv8 中使用 eval 函数执行表达式计算
在js 开发中我们都说eval 函数是邪恶的,但是此函数也有好多妙用,以下是几个简单的案例
eval 执行基于js 的表达式计算
比如我们有以下表
CREATE TABLE rules (
id SERIAL PRIMARY KEY,
rule_expression text
);
-- Indices -------------------------------------------------------
CREATE UNIQUE INDEX rules_pkey ON rules(id int4_ops);
- 表内容
INSERT INTO "public"."rules"("id","rule_expression")
VALUES
(1,E'"${vars_name}".length>10');
- plv8 函数
CREATE or replace FUNCTION rule_test(id int,args text) RETURNS json AS
$$
// 解决es 模版函数问题,string 转string template
String.prototype.interpolate = function(params) {
const names = Object.keys(params);
const vals = Object.values(params);
return new Function(
}
var result = {}
var plan = plv8.prepare('SELECT rule_expression from rules where id = $1',['int']);
// only for test fetch one row
var rule_row = plan.execute([ id ])[0];
let vars_name = args;
var rule_template = rule_row.rule_expression.interpolate({vars_name});
var execresult = eval(rule_template);
result = {
id: id,
validate: execresult
}
plan.free();
return JSON.stringify(result);
$$
LANGUAGE plv8;
- 调用函数
select * from rule_test(1,'ddssaa'); // return {"id":1,"validate":false}
select * from rule_test(1,'dddaaasssssssssaa'); // return {"id":1,"validate":true}
一个比较通用的基于eval 的规则校验
- 约定
通过vars. 进行key 的处理支持标准的js && || - 参考例子
"${vars.name}".length>10&& "${vars.version}"=="1.0"
- 函数定义
CREATE or replace FUNCTION rule_test3(id int,args json,rule_row text) RETURNS json AS
$$
String.prototype.interpolate = function(params) {
const names = Object.keys(params);
const vals = Object.values(params);
return new Function(
}
var result = {}
let vars = {
var rule_template = rule_row.interpolate({vars});
var execresult = eval(rule_template);
result = {
id: id,
validate: execresult
}
return JSON.stringify(result);
$$
LANGUAGE plv8;
- 调用
select a.*, rule_test3(3,'{"version":"1.0","name":"dddddddd"}',b.rule_expression) from apps a join rules b on a.id=b.id where a.id=2; /
// 2 rong {"id":3,"validate":false}
select a.*, rule_test3(3,'{"version":"1.0","name":"dddddd1111dd"}',b.rule_expression) from apps a join rules b on a.id=b.id where a.id=2;
// 2 rong {"id":3,"validate":true}
说明
以上是一个简单的使用plv8 使用js 实现的一个简单的规则判断,核心是对于string template 的函数处理
参考资料
https://plv8.github.io/#inline-statement-calls
https://github.com/plv8/plv8