You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

195 lines
4.2 KiB

package apijson
import (
"fmt"
"net/http"
"strings"
"time"
)
func NewQueryNode(c *QueryContext, path, key string, queryMap map[string]interface{}) *QueryNode {
n := &QueryNode{
ctx: c,
Key: strings.ToLower(key),
Path: path,
RequestMap: queryMap,
start: time.Now().UnixNano(),
sqlExecutor: &MysqlExecutor{},
isList: strings.HasSuffix(key, "[]"),
}
c.nodePathMap[path] = n
if n.isList {
n.parseList()
} else {
n.parseOne()
}
return n
}
type QueryNode struct {
ctx *QueryContext
start int64
depth int8
running bool
completed bool
isList bool
page interface{}
count interface{}
sqlExecutor *MysqlExecutor
primaryKey string
relateKV map[string]string
Key string
Path string
RequestMap map[string]interface{}
CurrentData map[string]interface{}
ResultList []map[string]interface{}
children map[string]*QueryNode
}
func (n *QueryNode) parseList() {
root := n.ctx
if root.err != nil {
return
}
if value, exists := n.RequestMap[n.Key[0:len(n.Key)-2]]; exists {
if kvs, ok := value.(map[string]interface{}); ok {
root.err = n.sqlExecutor.ParseTable(n.Key)
n.parseKVs(kvs)
} else {
root.err = fmt.Errorf("列表同名参数展开出错,listKey: %s, object: %v", n.Key, value)
root.code = http.StatusBadRequest
}
return
}
for field, value := range n.RequestMap {
if value == nil {
root.err = fmt.Errorf("field of [%s] value error, %s is nil", n.Key, field)
return
}
switch field {
case "page":
n.page = value
case "count":
n.count = value
default:
if kvs, ok := value.(map[string]interface{}); ok {
child := NewQueryNode(root, n.Path+"/"+field, field, kvs)
if root.err != nil {
return
}
if n.children == nil {
n.children = make(map[string]*QueryNode)
}
n.children[field] = child
if nonDepend(n, child) && len(n.primaryKey) == 0 {
n.primaryKey = field
}
}
}
}
}
func nonDepend(parent, child *QueryNode) bool {
if len(child.relateKV) == 0 {
return true
}
for _, v := range child.relateKV {
if strings.HasPrefix(v, parent.Path) {
return false
}
}
return true
}
func (n *QueryNode) parseOne() {
root := n.ctx
root.err = n.sqlExecutor.ParseTable(n.Key)
if root.err != nil {
root.code = http.StatusBadRequest
return
}
n.sqlExecutor.PageSize(0, 1)
n.parseKVs(n.RequestMap)
}
func (n *QueryNode) parseKVs(kvs map[string]interface{}) {
root := n.ctx
for field, value := range kvs {
if value == nil {
root.err = fmt.Errorf("field value error, %s is nil", field)
root.code = http.StatusBadRequest
return
}
if queryPath, ok := value.(string); ok && strings.HasSuffix(field, "@") { // @ 结尾表示有关联查询
if n.relateKV == nil {
n.relateKV = make(map[string]string)
}
fullPath := queryPath
if strings.HasPrefix(queryPath, "/") {
fullPath = n.Path + queryPath
}
n.relateKV[field[0:len(field)-1]] = fullPath
} else {
n.sqlExecutor.ParseCondition(field, value)
}
}
}
func (n *QueryNode) Result() interface{} {
if n.isList {
return n.ResultList
}
if len(n.ResultList) > 0 {
return n.ResultList[0]
}
return nil
}
func (n *QueryNode) doQueryData(ctx *QueryContext) {
if n.completed {
return
}
n.running = true
defer func() { n.running, n.completed = false, true }()
root := n.ctx
if len(n.relateKV) > 0 {
for field, queryPath := range n.relateKV {
value := root.findResult(queryPath)
if root.err != nil {
return
}
n.sqlExecutor.ParseCondition(field, value)
}
}
if !n.isList {
n.ResultList, root.err = n.sqlExecutor.Exec(ctx)
if len(n.ResultList) > 0 {
n.CurrentData = n.ResultList[0]
return
}
return
}
primary := n.children[n.primaryKey]
primary.sqlExecutor.PageSize(n.page, n.count)
primary.doQueryData(ctx)
if root.err != nil {
return
}
listData := primary.ResultList
n.ResultList = make([]map[string]interface{}, len(listData))
for i, x := range listData {
n.ResultList[i] = make(map[string]interface{})
n.ResultList[i][n.primaryKey] = x
primary.CurrentData = x
if len(n.children) > 0 {
for _, child := range n.children {
if child != primary {
child.doQueryData(ctx)
n.ResultList[i][child.Key] = child.Result()
}
}
}
}
}