Ai
1 Star 2 Fork 0

王军/query

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
schema.go 6.75 KB
一键复制 编辑 原始数据 按行查看 历史
王军 提交于 2023-03-10 20:02 +08:00 . 增加 mod
/*
* @Author: Wangjun
* @Date: 2021-06-08 11:35:05
* @LastEditTime: 2022-10-28 14:52:56
* @LastEditors: Wangjun
* @Description:查询schema
* @FilePath: \xrengined:\go\src\gitee.com\haodreams\query\schema.go
* hnxr
*/
package query
import (
"errors"
"fmt"
"log"
"runtime/debug"
"strings"
"time"
"gitee.com/haodreams/golib/logs"
"github.com/alecthomas/participle/v2"
)
type Schema struct {
Table string `parser:"'FROM' '(' @String ')'"`
Funcs []*Func `parser:"@@+"`
Err string //错误消息
initError error //初始化的错误
Result string //暂存数据的地方
Desc string //存放描述的地方
Query string
SourceQuery string //优化后的查询
LastRunTime int64 //最后一次运行时间
UsedTime string //耗时
Value string //运行结果
OK bool
q *Table
}
/**
* @description:获取快速表
* @param {*}
* @return {*}
*/
func (m *Schema) FastTable() (table *Table, err error) {
if !m.OK {
return
}
defer func() {
if e := recover(); e != nil {
m.Err = fmt.Sprint(e)
err = errors.New(m.Err)
m.OK = false
log.Println(e, string(debug.Stack()))
return
}
}()
now := time.Now()
m.LastRunTime = now.Unix()
n := len(m.Funcs)
q := m.q
for i := 0; i < n; i++ {
f := m.Funcs[i]
q, err = f.f(q, f.Params)
if err != nil {
m.OK = false
break
}
}
if err != nil {
m.Err = err.Error()
} else {
m.Err = ""
}
table = q
return
}
/**
* @description: 获取快速表(大表转小标)
* @param {string} s
* @return {*}
*/
func NewFastTable(s string) (table *Table, err error) {
schema, err := NewSchema(s)
if err != nil {
return
}
table, err = schema.FastTable()
return
}
/**
* @description: 开启优化查询,后面需要手动调用 Parser
* @param {string} s
* @return {*}
*/
func NewFastSchema(s string) (schema *Schema, err error) {
schema = new(Schema)
ss := strings.Split(s, ").")
if len(ss) < 3 {
err = schema.Parser(s)
if err != nil {
logs.Error(err)
}
return
}
schema.SourceQuery = s
pos := 0
for i, s := range ss {
if i == 0 {
continue
}
if strings.Contains(s, ".") {
pos = i
break
}
}
if pos > 1 {
key := strings.Join(ss[:pos], ").") + ")"
tableName := strings.ReplaceAll(key, "\"", "'")
tableName = strings.TrimSuffix(tableName, ".")
table := GetTable(tableName)
if table == nil {
table, err = NewFastTable(key)
if err != nil {
schema.Err = err.Error()
schema.initError = err
//logs.Error(err)
return schema, err
}
err = RegisterTable(tableName, table)
if err != nil {
schema.Err = err.Error()
logs.Error(err.Error())
return
}
}
query := strings.Replace(schema.SourceQuery, key, "FROM(\""+tableName+"\")", 1)
//log.Println(query)
err = schema.Parser(query)
} else {
err = schema.Parser(schema.SourceQuery)
}
if err != nil {
logs.Error(err)
schema.initError = err
}
return
}
/**
* @description: 不开启优化
* @param {string} s
* @return {*}
*/
func NewSchema(s string) (se *Schema, err error) {
se = new(Schema)
err = se.Parser(s)
return
}
// GetColumns 获取列名
func (m *Schema) GetColumns() []string {
return m.q.Keys()
}
// 初始化数据
func (m *Schema) Parser(s string) (err error) {
parse, err := participle.Build[Schema]()
if err != nil {
m.Err = err.Error()
return
}
t, err := parse.ParseString("", s)
if err != nil {
m.Err = err.Error()
return
}
m.Query = s
m.Funcs = t.Funcs
m.Table = t.Table
//整理数据
m.Table = strings.TrimPrefix(m.Table, "\"")
m.Table = strings.TrimSuffix(m.Table, "\"")
for _, f := range m.Funcs {
for _, p := range f.Params {
if p.String != nil {
*p.String = strings.TrimPrefix(*p.String, "\"")
*p.String = strings.TrimSuffix(*p.String, "\"")
}
}
}
//初始化数据表
m.q = GetTable(m.Table)
if m.q == nil {
err = fmt.Errorf("'%s' 数据表没有注册", m.Table)
m.Err = err.Error()
return
}
//初始化每个方法
for _, f := range m.Funcs {
if f == nil {
err = fmt.Errorf("'%s' 无效的函数调用", m.Table)
m.Err = err.Error()
return
}
if fn, ok := mq.mapFunc[f.Name]; ok {
f.f = fn
} else {
err = fmt.Errorf("'%s' 没有此函数 [%s]", m.Table, f.Name)
m.Err = err.Error()
return
}
if f.f == nil {
err = fmt.Errorf("'%s.%s' 无效的函数调用", m.Table, f.Name)
m.Err = err.Error()
return
}
if strings.HasPrefix(f.Name, "If") {
if len(f.Params) != 3 {
err = fmt.Errorf("'%s.%s' 参数个数错误", m.Table, f.Name)
m.Err = err.Error()
return
}
}
}
m.OK = true
return nil
}
// Eval 执行计算
func (m *Schema) Eval() (value interface{}, err error) {
if m.initError != nil {
return nil, m.initError
}
if !m.OK {
return
}
defer func() {
if e := recover(); e != nil {
m.Err = fmt.Sprint(e)
err = errors.New(m.Err)
m.OK = false
log.Println(e, string(debug.Stack()))
return
}
}()
now := time.Now()
m.LastRunTime = now.Unix()
n := len(m.Funcs)
q := m.q
for i := 0; i < n; i++ {
f := m.Funcs[i]
q, err = f.f(q, f.Params)
if err != nil {
break
}
}
if err != nil {
m.Err = err.Error()
} else {
m.Err = ""
}
m.UsedTime = time.Since(now).String()
value = q.Result()
switch v := value.(type) {
case float64:
m.Value = fmt.Sprintf("%.4f", v)
case float32:
m.Value = fmt.Sprintf("%.4f", v)
default:
m.Value = fmt.Sprint(value)
}
return
}
// 最后一个缺省是and运算
type QueryFunc func(*Table, []*Param) (*Table, error)
//type FuncStatic func(*Query, string) (interface{}, error)
// FORM("es").LT("Genpower.Value",0).GT("Genpower.Value",-5000).Sum("Genpower.Value")
type Func struct {
Name string `parser:"'.' @Ident"`
Params []*Param `parser:"'(' ( @@ ( ',' @@ )* )? ')'"`
f QueryFunc
//static FuncStatic `json:"-"`
}
func (m *Func) String() string {
s := "func:" + m.Name + " "
for _, p := range m.Params {
if p == nil {
continue
}
s += fmt.Sprint(",", p.GetValue())
}
return s
}
func (m *Func) Key() string {
return *m.Params[0].String
}
type Param struct {
Number *float64 `parser:"@('-'?(Float|Int))"`
String *string `parser:"| @String"`
}
func (m *Param) Key() string {
if m.String == nil {
return ""
}
return *m.String
}
func (m *Param) GetValue() interface{} {
if m.Number != nil {
return *m.Number
}
if m.String != nil {
return *m.String
}
return nil
}
func (m *Param) Float64() float64 {
if m.Number == nil {
return 0
}
return *m.Number
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/haodreams/query.git
git@gitee.com:haodreams/query.git
haodreams
query
query
97e1fcd00b97

搜索帮助