在插件的api.lua经常用到crud 类。例如
local crud = require "kong.api.crud_helpers"
crud.patch(self.params, dao_factory.nmg_cors, self.plugin)
crud.paginated_set(self, dao_factory.nmg_cors)
crud.find_plugin_by_filter(self, dao_factory, {
name = "nmg-plugin-cors"
}, helpers)
crud_helpers 是操作DB的封装类,它封装了find_by_id_or_field
,find_api_by_name_or_id
,find_plugin_by_filter
,paginated_set
,post
,patch
,put
,delete
等常用DB操作的方法。实际的DB操作是通过dao_collection类操作的。dao_factory.XXX 是api.lua的方法中的参数传递的,可以通过before 方法过滤查询条件。
--- Partial update of an entity.
-- Filter keys must be given to get the row to update.
function _M.patch(params, dao_collection, filter_keys, post_process)
if not next(params) then
return responses.send_HTTP_BAD_REQUEST("empty body")
end
local updated_entity, err = dao_collection:update(params, filter_keys)
if err then
return app_helpers.yield_error(err)
elseif updated_entity == nil then
return responses.send_HTTP_NOT_FOUND()
else
return responses.send_HTTP_OK(post_process_row(updated_entity, post_process))
end
end
真正执行更新的是dao_collection:update
。dao_collection对应的类是dao/dao.lua
。
--- Update a row.
-- Update a row in the related table. Perform a partial update by default (only fields in `tbl` will)
-- be updated. If asked, can perform a "full" update, replacing the entire entity (assuming it is valid)
-- with the one specified in `tbl` at once.
-- @param[type=table] tbl A table containing the new values for this row.
-- @param[type=table] filter_keys A table which must contain the primary key(s) to select the row to be updated.
-- @param[type=table] options Options to use for this update. (`full`: performs a full update of the entity, `quiet`: does not send event).
-- @treturn table res A table representing the updated entity.
-- @treturn table err If an error occurred, a table describing the issue.
function DAO:update(tbl, filter_keys, options)
options = options or {}
check_arg(tbl, 1, "table")
check_not_empty(tbl, 1)
check_arg(filter_keys, 2, "table")
check_not_empty(filter_keys, 2)
check_arg(options, 3, "table")
for k, v in pairs(filter_keys) do
if tbl[k] == nil then
tbl[k] = v
end
end
local model = self.model_mt(tbl)
local ok, err = model:validate {dao = self, update = true, full_update = options.full}
if not ok then
return ret_error(self.db.name, nil, err)
end
local primary_keys, values, nils, err = model:extract_keys()
if err then
return ret_error(self.db.name, nil, Errors.schema(err))
end
local old, err = self.db:find(self.table, self.schema, primary_keys)
if err then
return ret_error(self.db.name, nil, err)
elseif old == nil then
return
end
if not options.full then
fix(old, values, self.schema)
end
local res, err = self.db:update(self.table, self.schema, self.constraints, primary_keys, values, nils, options.full, model, options)
if err then
return ret_error(self.db.name, nil, err)
elseif res then
if not options.quiet then
if self.events then
local _, err = self.events.post_local("dao:crud", "update", {
schema = self.schema,
operation = "update",
entity = res,
old_entity = old,
})
if err then
ngx.log(ngx.ERR, "could not propagate CRUD operation: ", err)
end
end
end
return setmetatable(res, nil)
end
end
在执行更新之前会执行验证
local ok, err = model:validate {dao = self, update = true, full_update = options.full}
验证内容是plugin的schema和plugin的config是否匹配。验证类是dao/schemas_validation.lua
注意下面
-- Check for unexpected fields in the entity
for k in pairs(t) do
if schema.fields[k] == nil then
if schema.flexible then
if utils.strip(tk) ~= "" and k ~= tk then
errors = utils.add_error(errors, error_prefix .. k, k .. " is an unknown field")
end
else
errors = utils.add_error(errors, error_prefix .. k, k .. " is an unknown field")
end
end
end
这是比较plugins表的数据结构和shema的配置是否一致。t是table。shema是shema.lua的配置项。如果plugins表有值,而shema中没有,则会提示xxx is an unknown field
。例如我在某个plugin设置了route_id,但是shema中是没有的,就会出
{route_id:'route_id is an unknown field'}