本系列其他文章
dbrest v1.1公测版发布
dbrest配置说明
dbrestapi调用说明含样例代码
dbrest lua脚本模板
dbrest小试牛刀
dbrest压测结果
dbrest v1.1.0以上版本支持
lua脚本模板文件
--JSON = (loadfile "json.lua")()
--local g = require("clr")
--[[
该函数在主程序执行Insert之前触发,可以在此函数中对client提交的body进行修改
函数签名不得修改,即函数名称,参数以及返回类型
objArray: table类型, 存放json对象数组(client 提交到服务端的json object),该参数为引用类型(Pass By Reference)
return: 返回bool值true或者false,仅在返回值为true时,脚本中的修改才有效,否则忽略脚本中的修改
--]]
function beforeInsert(objArray)
--todo modify objArray
return true
end
--[[
该函数在主程序执行Insert后触发。
函数签名不得修改,即函数名称,参数以及返回类型
t: table类型,存放client提交到服务端的json数组,以及主程序执行insert后数据库返回自动增长ID数组
t.objArray: table类型,入参, 存放json对象数组(client 提交到服务端的json对象数组)
t.idArray: table类型, 入参,存放json整型数组,(自动增长ID)
t.sqlAndArgs: table类型,出参,可以往此table中添加要执行的sql语句及其参数值args,如果sql语句为非参数化sql,args可以忽略
样例:
t.sqlAndArgs[1] = {sql="INSERT INTO students_log (id,name,gender,age,class,remark) select id,name,gender,age,class,remark from students where id=?", args={1}}
t.sqlAndArgs[2] = {sql="INSERT INTO students_log (id,name,gender,age,class,remark) select id,name,gender,age,class,remark from students where id=100"}
t.sqlAndArgs[3] = {sql=string.format("INSERT INTO tab1(name, remark) VALUES('%s', '%s');",string.gsub(t.objArray[i]["tabs"][j]["name"],"'","''"), t.idArray[i])}
t.sqlAndArgs[4] = {sql="INSERT INTO tab1(name, remark) VALUES(?, ?);", args ={t.objArray[i]["tabs"][j]["name"], t.idArray[i]}}
--请注意mysql不支持以下命名参数形式
t.sqlAndArgs[5] = {sql="INSERT INTO tab1(name, remark) VALUES(:name, :remark);", args ={name=t.objArray[i]["tabs"][j]["name"], remark=t.idArray[i]}}
t.sqlAndArgs[6] = {sql="INSERT INTO tab1(name, remark) VALUES($name, $remark);", args ={name=t.objArray[i]["tabs"][j]["name"], remark=t.idArray[i]}}
return: 返回bool值true或者false,仅在返回值为true时,脚本中生成的sql语句才会执行
--]]
function afterInsert_buildSql(t)
--todo build sql
return true
end
--[[
该函数在主程序更新数据前触发
函数签名不得修改,即函数名称,参数以及返回类型
t: table类型,存放update语句的where语句以及其参数以及客户端提交的json object,可以往此table中写入需要在执行update前先执行的sql
t.where: string类型, 存放update语句的where字句(参数化的where子句)
t.args: 数组类型,存放update语句的where子句的参数值
t.obj: table类型, 存放json对象(client 提交到服务端的json object)
t.sqlAndArgs:table类型,可以往此table中添加要执行的sql语句及其参数值args,如果sql语句为非参数化sql,args可以忽略
例如参数化: t.sqlAndArgs[1] = {sql="update tab1 set remark='lua备注一下'"..t.where, args=args}
例如非参数化:t.sqlAndArgs[2] = {sql="update tab1 set remark='所有记录的备注都被修改了'"}
例子:update前,先将要更新的记录insert至该表的日志表中
t.sqlAndArgs[1] = {sql="INSERT INTO students_log (id,name,gender,age,class,remark) select id,name,gender,age,class,remark from students "..t.where, args=args}
return: 返回bool值true或者false,仅在返回值为true时,脚本中生成的sql语句才会执行
--]]
function beforeUpdate_buildSql(t)
--todo build sql
return true
end
--[[
该函数在主程序更新数据后触发
t: table类型,存放update语句的where语句以及其参数以及客户端提交的json object,可以往此table中写入需要在执行update后执行的sql
t.where: string类型, 存放update语句的where字句(参数化的where子句)
t.args: 数组类型,存放update语句的where子句的参数值
t.obj: table类型, 存放json对象(client 提交到服务端的json object)
t.sqlAndArgs:table类型,可以往此table中添加要执行的sql语句及其参数值args,如果sql语句为非参数化sql,args可以忽略
例如参数化: t.sqlAndArgs[1] = {sql="update tab1 set remark='lua备注一下'"..t.where, args=args}
例如非参数化:t.sqlAndArgs[2] = {sql="update tab1 set remark='所有记录的备注都被修改了'"}
例子:update订单明细表(order_items)后,汇总产品数量更新到订单主表(orders)中,(假设主表与明细表用order_id列关联)
t.sqlAndArgs[1] = {sql=string.format("update a set a.total_qty=b.sum_qty from orders as a inner join (select order_id, sum(qty) as sum_qty from order_items %s group by order_id) as b on a.order_id=b.order_id", t.where), args=args}
return: 返回bool值true或者false,仅在返回值为true时,脚本中生成的sql语句才会执行
--]]
function afterUpdate_buildSql(t)
--todo build sql
return true
end
--[[
该函数在主程序删除数据前触发
t: table类型,存放delete语句的where语句以及其参数,可以往此table中写入需要在执行delete前先执行的sql
t.where: string类型, 存放delete语句的where字句(参数化的where子句)
t.args: 数组类型,存放delete语句的where子句的参数值
t.sqlAndArgs:table类型,可以往此table中添加要执行的sql语句及其参数值args,如果sql语句为非参数化sql,args可以忽略
例如删除前,先将要删除的记录insert至该表的日志表中
t.sqlAndArgs[1] = {sql="INSERT INTO students_log (id,name,gender,age,class,remark) select id,name,gender,age,class,remark from students "..t.where, args=args}
return: 返回bool值true或者false,仅在返回值为true时,脚本中生成的sql语句才会执行
--]]
function beforeDelete_buildSql(t)
--todo build sql
return true
end
- lua脚本样例
JSON = (loadfile "json.lua")()
--"json.lua" 模块说明
--string JSON:encode(object) --lua对象序列化为json字符串
--object JSON:decode(encode) --json字符串反序列化为lua对象
local g = require("clr")
--[[
"clr" 模块是dbrest内部提供的lua扩展模块
lua print函数被clr重写,等同于clr模块中的log函数
clr 函数清单:
void log(...args) --打印日志
void print(...args) --控制台打印
string getCurrentPath() --返回main process当前路径
bool pathExists(string) --返回指定路径是否存在
bool isDir(string) --返回指定路径是否是目录
string encode(object) --lua对象序列化为json字符串
object decode(string) --json字符串反序列化为lua对象
string md5(string) --md5函数
string base64Encode(string) --base64编码
string base64Decode(string) --base64解码
string guid() --guid,uuid生成函数
(int status, string body, string error) requests(string method, string url, string queryParams, string headers, string data) --http请求函数
--[[
参数说明:
1)method: http method,样例:GET,POST,PUT,PATCH,DELETE
2)url: 请求地址,样例:http://wwww.baidu.com
3)queryParams: json格式查询参数,样例:{"name":"zhangsan","age":20};
url配合queryParams构成完整url:http://www.baidu.com?name=zhangsan&age=20
4)headers: json格式,样例:{"Authorization": "Basic Y2xpZW50MTphYmNkZQ==","Content-Type": "application/json"}
5)data:http 请求的body部分。
返回值说明:
1)status:http status code
2)body: http response body
3)error: 错误信息
调用demo:
g.log("记录一行日志")
g.log(1)
g.log(true)
g.print("控制台显示的msg")
str = g.getCurrentPath()
g.print("当前路径:"..tostring(str))
g.print(g.pathExists("f:\abc\def"))
fruits = {"banana","orange","apple"}
jsonStr = g.encode(fruits)
g.print(jsonStr)
jsonStr = '[{"name":"Tom","gender":"男","age":20,"class":"一班","logondate":"2020-09-02"},{"name":"Jack","gender":"男","age":20,"class":"一班","logondate":"2020-09-02"}]'
persons = g.decode(jsonStr)
g.print("数组长度"..#persons)
g.print(persons[1]["name"])
g.print(persons[2]["name"])
g.print(g.md5("hello,world!"))
g.print(g.guid())
str1 = g.base64Encode("hello,world!")
g.print(str1)
g.print(g.base64Decode(str1))
status,body,error=g.requests("GET","https://www.baidu.com","","","")
g.print(status)
g.print(body)
g.print(error)
status,body,error=g.requests("GET","https://www.infoswap.cn/api/students",'{"id":"lt.20"}',"","")
g.print(status)
g.print(body)
g.print(error)
--]]
--[[
该函数在主程序执行Insert之前触发,可以在此函数中对client提交的body进行修改
函数签名不得修改,即函数名称,参数以及返回类型
function beforeInsert(objArray)
return true/false
end
objArray: table类型, 存放json对象数组(client 提交到服务端的json object),该参数为引用类型(Pass By Reference)
return: 返回bool值true或者false,仅在返回值为true时,脚本中的修改才有效,否则忽略脚本中的修改
--]]
function beforeInsert(objArray)
--local objArray = JSON:decode(objArrayStr)
print(#objArray)
for i=1, #objArray do
objArray[i]["remark"] = "lua reamrk"
if objArray[i]["name"] ~= nil then
objArray[i]["name"] = string.upper(objArray[i]["name"])
end
if objArray[i]["tabs"] ~= nil and #objArray[i]["tabs"]>0 then
for j =1, #objArray[i]["tabs"] do
if objArray[i]["tabs"][j]["name"] ~= nil then
objArray[i]["tabs"][j]["name"] = string.upper(objArray[i]["tabs"][j]["name"])
end
end
end
end
return true
end
--[[
该函数在主程序执行Insert后触发。
t: table类型,存放client提交到服务端的json数组,以及主程序执行insert后数据库返回自动增长ID数组
t.objArray: table类型,入参, 存放json对象数组(client 提交到服务端的json对象数组)
t.idArray: table类型, 入参,存放json整型数组,(自动增长ID)
t.sqlAndArgs: table类型,出参,可以往此table中添加要执行的sql语句及其参数值args,如果sql语句为非参数化sql,args可以忽略
样例:
t.sqlAndArgs[1] = {sql="INSERT INTO students_log (id,name,gender,age,class,remark) select id,name,gender,age,class,remark from students where id=?", args={1}}
t.sqlAndArgs[2] = {sql="INSERT INTO students_log (id,name,gender,age,class,remark) select id,name,gender,age,class,remark from students where id=100"}
t.sqlAndArgs[3] = {sql=string.format("INSERT INTO tab1(name, remark) VALUES('%s', '%s');",string.gsub(t.objArray[i]["tabs"][j]["name"],"'","''"), t.idArray[i])}
t.sqlAndArgs[4] = {sql="INSERT INTO tab1(name, remark) VALUES(?, ?);", args ={t.objArray[i]["tabs"][j]["name"], t.idArray[i]}}
--请注意mysql不支持以下命名参数形式
t.sqlAndArgs[5] = {sql="INSERT INTO tab1(name, remark) VALUES(:name, :remark);", args ={name=t.objArray[i]["tabs"][j]["name"], remark=t.idArray[i]}}
t.sqlAndArgs[6] = {sql="INSERT INTO tab1(name, remark) VALUES($name, $remark);", args ={name=t.objArray[i]["tabs"][j]["name"], remark=t.idArray[i]}}
return: 返回bool值true或者false,仅在返回值为true时,脚本中生成的sql语句才会执行
--]]
function afterInsert_buildSql(t)
index = 1
for i=1, #t.objArray do
if t.objArray[i]["tabs"] ~= nil and #t.objArray[i]["tabs"] > 0 then
for j =1, #t.objArray[i]["tabs"] do
--t.sqlAndArgs[index] = {sql=string.format("INSERT INTO tab1(name, remark) VALUES('%s', '%s');",string.gsub(t.objArray[i]["tabs"][j]["name"],"'","''"), t.idArray[i])}
t.sqlAndArgs[index] = {sql="INSERT INTO tab1(name, remark) VALUES(?, ?);", args ={t.objArray[i]["tabs"][j]["name"], t.idArray[i]}}
--t.sqlAndArgs[index] = {sql="INSERT INTO tab1(name, remark) VALUES(:name, :remark);", args ={name=t.objArray[i]["tabs"][j]["name"], remark=t.idArray[i]}}
--t.sqlAndArgs[index] = {sql="INSERT INTO tab1(name, remark) VALUES($name, $remark);", args ={name=t.objArray[i]["tabs"][j]["name"], remark=t.idArray[i]}}
index = index+1
end
end
end
return true
end
--clone object
local function clone(obj)
local result
if type(obj) == "table" then
result = {}
--for k,v in next, obj, nil do
for k, v in pairs(obj) do
result[clone(k)] = clone(v)
end
else -- number, string, boolean, etc
result = obj
end
return result
end
--[[
该函数在主程序更新数据前触发
t: table类型,存放update语句的where语句以及其参数以及客户端提交的json object,可以往此table中写入需要在执行update前先执行的sql
t.where: string类型, 存放update语句的where字句(参数化的where子句)
t.args: 数组类型,存放update语句的where子句的参数值
t.obj: table类型, 存放json对象(client 提交到服务端的json object)
t.sqlAndArgs:table类型,可以往此table中添加要执行的sql语句及其参数值args,如果sql语句为非参数化sql,args可以忽略
例如参数化: t.sqlAndArgs[1] = {sql="update tab1 set remark='lua备注一下'"..t.where, args=args}
例如非参数化:t.sqlAndArgs[2] = {sql="update tab1 set remark='所有记录的备注都被修改了'"}
例子:update前,先将要更新的记录insert至该表的日志表中
t.sqlAndArgs[1] = {sql="INSERT INTO students_log (id,name,gender,age,class,remark) select id,name,gender,age,class,remark from students "..t.where, args=args}
return: 返回bool值true或者false,仅在返回值为true时,脚本中生成的sql语句才会执行
--]]
function beforeUpdate_buildSql(t)
print(t.where)
print(JSON:encode(t.args))
print(JSON:encode(t.obj))
args2=clone(t.args)
table.insert(args2,1,"lua添加的参数")
--t.sqlAndArgs[1] = {sql="update tab1 set remark=? "..t.where, args=args2}
--t.sqlAndArgs[2] = {sql="update tab1 set remark2=getdate() where id=3"}
t.sqlAndArgs[3] = {sql="INSERT INTO students_log(id,name,gender,age,class,remark) select id,name,gender,age,class,remark from students "..t.where, args=t.args}
return true
end
--[[
该函数在主程序删除数据前触发
t: table类型,存放delete语句的where语句以及其参数,可以往此table中写入需要在执行delete前先执行的sql
t.where: string类型, 存放delete语句的where字句(参数化的where子句)
t.args: 数组类型,存放delete语句的where子句的参数值
t.sqlAndArgs:table类型,可以往此table中添加要执行的sql语句及其参数值args,如果sql语句为非参数化sql,args可以忽略
例如删除前,先将要删除的记录insert至该表的日志表中
t.sqlAndArgs[1] = {sql="INSERT INTO students_log (id,name,gender,age,class,remark) select id,name,gender,age,class,remark from students "..t.where, args=args}
return: 返回bool值true或者false,仅在返回值为true时,脚本中生成的sql语句才会执行
--]]
function beforeDelete_buildSql(t)
print(t.where)
print(JSON:encode(t.args))
args2=clone(t.args)
--table.insert(args2,1,"lua添加的参数")
t.sqlAndArgs[1] = {sql=[[INSERT INTO students_log (id,name,gender,age,class,remark,remark2,logondate,createdate,height,weight,delete_flag)
select id,name,gender,age,class,remark,remark2,logondate,createdate,height,weight,delete_flag from students ]]..t.where, args=args2}
return true
end