AuthPlatform/src/share/model.lua

417 lines
12 KiB
Lua

local Database = require('share.database')
local conf = require("config")
local helpers = require('share.helpers')
local implode = helpers.implode
local unique = helpers.unique
local table_remove = helpers.table_remove
local _M = {}
local WRITE = 'WRITE'
local READ = 'READ'
local database_write = Database:new({
host = conf.POSTGRES.host,
port = conf.POSTGRES.port,
user = conf.POSTGRES.user,
password = conf.POSTGRES.password,
database = conf.POSTGRES.database,
--charset = conf.POSTGRES.charset,
--timeout = conf.POSTGRES.timeout,
db_pool_timeout = conf.POSTGRES.pool_timeout,
db_pool_size = conf.POSTGRES.pool_size,
db_type = WRITE
})
local database_read = Database:new({
host = conf.POSTGRES.host,
port = conf.POSTGRES.port,
user = conf.POSTGRES.user,
password = conf.POSTGRES.password,
database = conf.POSTGRES.database,
--charset = conf.POSTGRES.charset,
--timeout = conf.POSTGRES.timeout,
db_pool_timeout = conf.POSTGRES.pool_timeout,
db_pool_size = conf.POSTGRES.pool_size,
db_type = READ
})
local function transform_value(value)
if value == ngx.null then
value = ''
end
value = value or ''
if string.lower(value) == 'null' then
return 'NULL'
end
return ngx.quote_sql_str(value)
end
-- return whole relations keys
--获取整个关系的键值
function _M:get_relation_local_index(parents)
local ids = {}
for key,parent in pairs(parents) do
table.insert( ids, parent[self.relation.local_key] )
end
return ids
end
-- return whole relation models
function _M:retrieve_relations(ids)
-- if table is empty
if next(ids) == nil then
return {}
end
local ids_str = implode(unique(ids))
self.relation_sql = 'select * from \"'..self.relation.model.table..'\" where ' .. self.relation.foreign_key .. ' in (' .. ids_str .. ')'
return table_remove(self:query(self.relation_sql, READ), self.relation.model:get_hidden())
end
-- return current parent node
function _M:merge_one_relation(parent, relations)
for _, item in pairs(relations) do
if (parent[self.relation.local_key] == item[self.relation.foreign_key]) then
parent[self.relation.key_name] = item
end
end
return parent
end
function _M:merge_many_relations(parent, relations)
for index, item in pairs(relations) do
if (parent[self.relation.local_key] == item[self.relation.foreign_key]) then
if not parent[self.relation.key_name] then
parent[self.relation.key_name] = {}
end
table.insert(parent[self.relation.key_name], item)
end
end
return parent
end
function _M:make_relations(parents)
if self.relation.mode ~= 0 then
local relations = self:retrieve_relations(self:get_relation_local_index(parents))
for key, parent in pairs(parents) do
if self.relation.mode == 1 then
-- belongs to
if table.getn(relations) > 0 then
parents[key] = self:merge_one_relation(parent, relations)
else
parents[key][self.relation.key_name] = nil
end
elseif self.relation.mode == 2 then
-- has many
parents[key] = self:merge_many_relations(parent, relations)
end
end
end
return parents
end
-- function _M:merge_hidden()
-- if #self.attributes == 0 then
-- return '*'
-- else
-- local result = table_remove(self.attributes, self.hidden)
-- return table.concat(result, ", ")
-- end
-- end
function _M:find(id,column)
if self.query_sql ~= nil then
ngx.log(ngx.ERR, 'cannot use find() with other query sql')
return 1, nil
end
column = column or 'id'
id = transform_value(id)
ngx.log(ngx.INFO, 'table name :' .. self.table)
local sql = 'select * from \"'..self.table..'\" where '..column..'='..id..' limit 1'
ngx.log(ngx.INFO, 'query sql:', sql)
local code, res = self:query(sql, READ)
if code == 0 then
if table.getn(res) > 0 then
ngx.log(ngx.INFO, 'query record count:', table.getn(res))
res = self:make_relations(res)
return code, res
end
end
return code, nil
end
function _M:all()
if self.query_sql ~= nil then
ngx.log(ngx.ERR, 'cannot use all() with other query sql ', self.query_sql)
return 2, nil
end
local code, res = self:query('select * from \"'..self.table..'\"', READ)
return code, self:make_relations(res)
end
--组装sql语句条件为and相关的字段
function _M:where(column,operator,value)
value = transform_value(value)
if not self.query_sql then
self.query_sql = 'where '..column.. ' ' .. operator .. ' ' .. value
else
self.query_sql = self.query_sql..' and '..column..' '..operator..' '..value
end
return self
end
--组装sql语句条件为or相关的字段
function _M:orwhere(column,operator,value)
value = transform_value(value)
if not self.query_sql then
return ngx.log(ngx.ERR,'orwhere function need a query_sql prefix')
else
self.query_sql = self.query_sql..' or '..column..operator..value
end
return self
end
function _M:orderby(column,operator)
local operator = operator or 'asc'
if not self.query_sql then
self.query_sql = 'order by '.. self.table .. '.' .. column .. ' ' ..operator
else
if self.has_order_by then
self.query_sql = self.query_sql .. ',' .. column.. ' ' ..operator
else
self.query_sql = self.query_sql .. ' order by ' .. column.. ' ' ..operator
end
end
self.has_order_by = true
return self
end
--获取数据表中记录的数量
function _M:count()
local sql = ""
if self.query_sql ~= nil then
sql = 'select count(*) from \"'..self.table..'\" '..self.query_sql
else
sql = 'select count(*) from \"'..self.table.."\""
end
local code, res = self:query(sql, READ)
if code == 0 then
if table.getn(res) > 0 then
return code, tonumber(res[1]['count'])
end
end
return code, nil
end
-- params: (option)int num
-- return: table
function _M:get(num)
num = num or nil
local limit_sql = ''
if num ~= nil then
limit_sql = 'limit ' .. num
end
if not self.query_sql then
ngx.log(ngx.ERR,'do not have query sql str')
return 2,nil
end
local sql = 'select * from \"'..self.table..'\" '..self.query_sql .. ' ' .. limit_sql
local code,res = self:query(sql, READ)
if self.relation.local_key ~= nil then
return code, self:make_relations(res)
end
return code, res
end
--根据数据模型中的
function _M:paginate(pageNum, pageSize)
ngx.log(ngx.INFO, "pageNum:", tostring(pageNum), " pageSize:", tostring(pageSize))
pageNum = pageNum or 1
pageSize = pageSize or 10
local sql, count_sql, total, code, res
local data={
data = {},
total = 0
}
if not self.query_sql then
sql = 'select * from \"'..self.table..'\" limit '..tostring(pageSize)..' offset '..tostring((pageNum - 1) * pageSize)
count_sql = 'select count(*) from \"'..self.table..'\"'
else
sql = 'select * from \"'..self.table .. '\" '..self.query_sql .. ' limit '..tostring(pageSize)..' offset '..tostring((pageNum - 1) * pageSize)
count_sql = 'select count(*) from \"'..self.table..'\" '..self.query_sql
end
code, total = self:query(count_sql, READ)
if code == 0 then
data['total'] = tonumber(total[1]['count'])
end
code, res = self:query(sql, READ)
if code == 0 then
data['data'] = self:make_relations(res)
end
return code, data
end
--返回数据表中的第一条数据记录
function _M:first()
if not self.query_sql then
ngx.log(ngx.ERR,'do not have query sql str')
return 2,nil
end
local sql = 'select * from \"'..self.table..'\" '..self.query_sql..' limit 1'
local code, res = self:query(sql, READ)
if next(res) ~= nil then
res = self:make_relations(res)
return code, res[1]
end
return code, nil
end
--插入数据内容到数据表中
function _M:create(data)
local columns,values
for column,value in pairs(data) do
value = transform_value(value)
if not columns then
columns = column
values = value
else
columns = columns..','..column
values = values..','..value
end
end
return self:query('insert into \"'..self.table..'\"('..columns..') values('..values..')', WRITE)
end
function _M:with(relation)
self.relation.key_name = relation
if self[relation] == nil then
ngx.log(ngx.ERR, self.table .. ' dont have ' .. relation .. ' function')
end
return self[relation]()
end
-- 使用数组来存储关系模型
function _M:has_many(model, foreign_key, local_key)
self.relation.model = model
self.relation.local_key = local_key
self.relation.foreign_key = foreign_key
self.relation.mode = 2
return self
end
function _M:belongs_to(model, foreign_key, local_key)
self.relation.model = model
self.relation.local_key = local_key
self.relation.foreign_key = foreign_key
self.relation.mode = 1
return self
end
--根据id删除数据库中的数据记录
function _M:delete(id)
id = id or nil
if not id then
-- 拼接需要delete的字段
if self.query_sql then
--postgres 数据库使用delete语句时不支持limit
--local sql = 'delete from \"'..self.table..'\" '..self.query_sql..' limit 1'
local sql = 'delete from \"'..self.table..'\" '..self.query_sql
return self:query(sql, WRITE)
end
ngx.log(ngx.ERR,'delete function need prefix sql')
return 2, nil
end
--return self:query('delete from '..self.table..' where id=' .. id .. ' limit 1', WRITE)
return self:query('delete from \"'..self.table..'\" where id='.. id, WRITE)
end
--软删除数据,不从数据表中删除记录,只将定义表中的字段值进行处理
--function _M:soft_delete()
-- if self.query_sql then
-- local sql = 'update '..self.table..' set '..self.soft_delete_column..' = now() '.. self.query_sql ..' limit 1'
-- return self:query(sql, WRITE)
-- end
-- ngx.log(ngx.ERR,'soft_delete function cannot called without restriction')
-- ngx.exit(500)
-- return false
--end
--更新数据表中的数据记录
function _M:update(data)
-- 拼接需要update的字段
local str = nil
for column,value in pairs(data) do
local clean_value = transform_value(value)
if not str then
str = column..'='..clean_value
else
str = str..','..column..'='..clean_value
end
end
-- 判断是模型自身执行update还是数据库where限定执行
if self.query_sql then
--postgres 数据库使用update语句时不支持limit
--local sql = 'update \"'..self.table..'\" set '..str..' '..self.query_sql..' limit 1'
local sql = 'update \"'..self.table..'\" set '..str..' '..self.query_sql
return self:query(sql, WRITE)
end
ngx.log(ngx.ERR,'update function cannot called without restriction')
return 2, nil
end
--查询数据表中的数据记录
function _M:query(sql, type)
if not sql then
ngx.log(ngx.ERR,'query() function need sql to query')
return 2, nil
end
self.query_sql = nil
self.has_order_by = false
if type == READ then
local code, result = database_read:db_query(sql)
if code ~= 0 then
ngx.log(ngx.ERR, "read db error. res: " .. tostring(code).." or no reason")
return code, nil
end
return code, result
elseif type == WRITE then
local code, result = database_write:db_query(sql)
if code ~= 0 then
ngx.log(ngx.ERR, "write db error. res: " .. (code or "no reason"))
return code, nil
end
return code, result
end
ngx.log(ngx.ERR, 'type invalid, need ' .. READ .. ' or '..WRITE)
return 2, nil
end
--获取需要隐藏的列
function _M:get_hidden()
return self.hidden
end
function _M:debug()
ngx.log(ngx.INFO, self.table.." ")
end
--初始化数据表中的字段
function _M:new(table, attributes, hidden)
local obj = {
table = table,
attributes = attributes or {},
hidden = hidden or {},
query_sql = nil,
has_order_by = false,
relation = {
mode = 0
},
relation_sql = nil,
--soft_delete_column = 'deleted_at'
}
setmetatable(obj, {__index = _M})
return obj
end
return _M