Ai
1 Star 2 Fork 0

王军/query

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
table.go 11.94 KB
一键复制 编辑 原始数据 按行查看 历史
王军 提交于 2023-03-17 09:35 +08:00 . 提升分类
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568
/*
* @Author: Wangjun
* @Date: 2021-05-27 14:34:55
* @LastEditTime: 2022-09-14 18:37:48
* @LastEditors: Wangjun
* @Description:
* @FilePath: \xrengined:\go\src\gitee.com\haodreams\query\table.go
* hnxr
*/
package query
import (
"errors"
"reflect"
"gitee.com/haodreams/libs/easy"
)
var (
errNoData = errors.New("无数据")
errNoOkData = errors.New("没有符合条件的数据")
)
/**
* @description: 查找给定值的值
* @param {reflect.Value} v
* @param {[]int} index
* @return {*}
*/
func FieldByIndex(v reflect.Value, index []int) (rv reflect.Value, err error) {
if len(index) == 1 {
return v.Field(index[0]), nil
}
// v.mustBe(Struct)
for i, x := range index {
if i > 0 {
if v.Kind() == reflect.Ptr && v.Type().Elem().Kind() == reflect.Struct {
if v.IsNil() {
//panic("reflect: indirection through nil pointer to embedded struct")
err = errors.New("reflect: indirection through nil pointer to embedded struct")
return
}
v = v.Elem()
}
}
v = v.Field(x)
}
return v, nil
}
type Table struct {
key map[string][]int
arrayObject interface{}
parent interface{} //父级数据用于OR操作
//err error //错误消息
result interface{} //保存的结果
}
/**
* @description: 获取记录集
* @param {*}
* @return {*}
*/
func (m *Table) Rows() interface{} {
return m.arrayObject
}
/**
* @description: 获取父记录集
* @param {*}
* @return {*}
*/
func (m *Table) ParentRows() interface{} {
return m.parent
}
// Result 计算的结果
func (m *Table) Result() interface{} {
return m.result
}
/**
* @description: 获取字段名
* @param {*}
* @return {*}
*/
func (m *Table) Keys() (keys []string) {
for key := range m.key {
keys = append(keys, key)
}
return keys
}
// GetError 获取错误
// func (m *Table) GetError() error {
// return m.err
// }
// 新建一个查询
func NewTable(objects interface{}) (q *Table, err error) {
q = new(Table)
q.arrayObject = objects
q.parent = objects
err = q.init()
if err != nil {
return nil, err
}
return
}
func (m *Table) init() (err error) {
//关联key的索引
t := reflect.TypeOf(m.arrayObject)
if !(t.Kind() == reflect.Slice || t.Kind() == reflect.Array) {
err = errors.New("参数错误,参数必须是结构体切片或者数组")
return
}
//log.Println(t.Kind(), t.String())
t = t.Elem()
m.key = map[string][]int{}
//log.Println(t.Elem(), t.Kind())
if t.Kind() == reflect.Ptr {
t = t.Elem()
}
if t.Kind() != reflect.Struct {
err = errors.New("数组的内容不是结构体")
return
}
m.initKey("", nil, t)
//TODO 查找GUID 字段并赋值,GUID 必须是int类型
return
}
func (m *Table) initKey(prefix string, paths []int, t reflect.Type) {
if t.Kind() == reflect.Ptr {
t = t.Elem()
}
//log.Println(prefix + t.String())
for i := 0; i < t.NumField(); i++ {
newPaths := make([]int, len(paths))
copy(newPaths, paths)
newPaths = append(newPaths, i)
fieldType := t.Field(i)
typ := fieldType.Type
if typ.Kind() == reflect.Ptr {
typ = typ.Elem()
}
//log.Println(prefix+fieldType.Name, typ.Kind())
if fieldType.Anonymous {
if typ.Kind() == reflect.Struct {
m.initKey(prefix, newPaths, typ)
} else {
m.key[prefix+fieldType.Name] = newPaths
//log.Println("field", fieldType.Name, typ.Kind())
}
continue
}
if typ.Kind() == reflect.Struct {
if fieldType.Name == "" {
continue
}
if fieldType.Name[0] >= 'A' && fieldType.Name[0] <= 'Z' {
//m.initKey(prefix+fieldType.Name+".", newPaths, field)
m.initKey(prefix+fieldType.Name+".", newPaths, typ)
}
continue
}
if fieldType.Name[0] >= 'A' && fieldType.Name[0] <= 'Z' {
m.key[prefix+fieldType.Name] = newPaths
}
}
}
/**
* @description: 过虑满足条件的数据
* @param {*Query} m
* @return {*}
*/
func (m *Table) orFilter(
key string,
value interface{},
intFunc func(a, b int64) bool,
floatFunc func(a, b float64) bool,
stringFunc func(a, b string) bool,
) (arr *Table, err error) {
arr = new(Table)
arr.key = m.key
//or 运算,继承父对象
arr.parent = m.parent
v := reflect.ValueOf(m.parent)
n, valueType, ids, err := m.checkPreconditionsOr(v, key)
if err != nil {
if !(err == errNoData || err == errNoOkData) {
return
}
}
floatValue := 0.0
intValue := int64(0)
stringValue := ""
mp := m.add2Map()
//如果值类型是数字,则参数类型必须是数字
if valueType != easy.TypeString {
paramType := easy.GetType(value)
if paramType == easy.TypeNull || paramType == easy.TypeString {
err = errors.New("参数类型和值类型不一致")
return
}
}
switch valueType {
case easy.TypeFloat:
floatValue, _ = easy.GetFloat64(value)
case easy.TypeInt:
intValue, _ = easy.GetInt64(value)
case easy.TypeString:
stringValue = value.(string)
default:
err = errors.New("不支持的数据类型")
return
}
for i := 0; i < n; i++ {
field := v.Index(i)
if field.Kind() == reflect.Ptr {
if field.IsNil() {
continue
}
}
addr := field.Pointer()
elem := reflect.Indirect(field)
if elem.IsValid() && !elem.CanInterface() {
continue
}
//ie := elem.Interface()
//log.Println(ie)
if !elem.IsValid() {
continue
}
elem, err = FieldByIndex(elem, ids)
if err != nil {
continue
}
if !elem.CanInterface() {
continue
}
switch valueType {
case easy.TypeFloat:
fval, err := easy.GetFloat64(elem.Interface())
if err != nil {
continue
}
if floatFunc(fval, floatValue) {
if _, ok := mp[addr]; !ok {
mp[addr] = field
}
} else {
continue
}
case easy.TypeInt:
ival, err := easy.GetInt64(elem.Interface())
if err != nil {
continue
}
if intFunc(ival, intValue) {
if _, ok := mp[addr]; !ok {
mp[addr] = field
}
} else {
continue
}
case easy.TypeString:
if stringFunc(elem.String(), stringValue) {
if _, ok := mp[addr]; !ok {
mp[addr] = field
}
} else {
continue
}
default:
continue
}
}
if len(mp) == 0 {
err = errNoOkData
} else {
vals := reflect.MakeSlice(v.Type(), len(mp), n)
count := 0
for _, val := range mp {
vals.Index(count).Set(val)
count++
}
arr.arrayObject = vals.Interface()
err = nil
}
return
}
/**
* @description: row (*struct) 加入到map
* @param {*}
* @return {*}key=struct 地址
*/
func (m *Table) add2Map() (mp map[uintptr]reflect.Value) {
mp = map[uintptr]reflect.Value{}
if m.arrayObject == nil {
return
}
v := reflect.ValueOf(m.arrayObject)
if v.IsZero() {
return
}
n := v.Len()
if n == 0 {
return
}
for i := 0; i < n; i++ {
field := v.Index(i)
if field.Kind() == reflect.Ptr {
if field.IsNil() {
continue
}
}
addr := field.Pointer()
mp[addr] = field
}
return
}
/**
* @description: 过虑满足条件的数据
* @param {*Query} m
* @return {*}
*/
func (m *Table) filter(
isAnd bool, //是否是and运算
key string,
value interface{},
intFunc func(a, b int64) bool,
floatFunc func(a, b float64) bool,
stringFunc func(a, b string) bool,
) (arr *Table, err error) {
if !isAnd {
return m.orFilter(key, value, intFunc, floatFunc, stringFunc)
}
arr = new(Table)
arr.key = m.key
if key == "" {
err = errors.New("缺少列名")
return
}
arr.parent = m.arrayObject
v := reflect.ValueOf(m.arrayObject)
n, valueType, ids, err := m.checkPreconditions(v, key)
if err != nil {
return
}
floatValue := 0.0
intValue := int64(0)
stringValue := ""
//如果值类型是数字,则参数类型必须是数字
if valueType != easy.TypeString {
paramType := easy.GetType(value)
if paramType == easy.TypeNull || paramType == easy.TypeString {
err = errors.New("参数类型和值类型不一致")
return
}
}
switch valueType {
case easy.TypeFloat:
floatValue, _ = easy.GetFloat64(value)
case easy.TypeInt:
intValue, _ = easy.GetInt64(value)
case easy.TypeString:
stringValue = value.(string)
default:
err = errors.New("不支持的数据类型")
return
}
vals := reflect.MakeSlice(v.Type(), n, n)
count := 0
for i := 0; i < n; i++ {
field := v.Index(i)
if field.Kind() == reflect.Ptr {
if field.IsNil() {
continue
}
}
elem := reflect.Indirect(field)
if elem.IsValid() && !elem.CanInterface() {
continue
}
//ie := elem.Interface()
//log.Println(ie)
if !elem.IsValid() {
continue
}
elem, err = FieldByIndex(elem, ids)
if err != nil {
continue
}
if !elem.CanInterface() {
continue
}
switch valueType {
case easy.TypeFloat:
fval, err := easy.GetFloat64(elem.Interface())
if err != nil {
continue
}
if floatFunc(fval, floatValue) {
vals.Index(count).Set(field)
} else {
continue
}
case easy.TypeInt:
ival, err := easy.GetInt64(elem.Interface())
if err != nil {
continue
}
if intFunc(ival, intValue) {
vals.Index(count).Set(field)
//log.Printf("%v", field.Type().String())
} else {
continue
}
case easy.TypeString:
if stringFunc(elem.String(), stringValue) {
vals.Index(count).Set(field)
} else {
continue
}
default:
continue
}
count++
}
if count > 0 {
x := reflect.New(v.Type())
x.Elem().Set(vals)
x.Elem().SetLen(count)
arr.arrayObject = x.Elem().Interface()
} else {
err = errNoOkData
}
return arr, err
}
//
/**
* @description: 检查field 是否可用
* @param {reflect.Value} v
* @return {*}
*/
func (m *Table) checkField(field reflect.Value, ids []int) (elem reflect.Value, ok bool) {
if field.Kind() == reflect.Ptr {
if field.IsNil() {
return field, false
}
}
elem = reflect.Indirect(field)
// if elem.IsValid() && !elem.CanInterface() {
// return field, false
// }
if !elem.IsValid() {
return field, false
}
elem, err := FieldByIndex(elem, ids)
if err != nil {
ok = false
return
}
if !elem.CanInterface() {
return field, false
}
return elem, true
}
/**
* @description: 前置条件的验证
* @param {reflect.Value} v
* @param {string} key
* @param {bool} setError
* @return {*}
*/
func (m *Table) checkPreconditions(v reflect.Value, key string) (size int, valueType byte, ids []int, err error) {
ids, ok := m.key[key]
if !ok {
err = errors.New("没有此列名" + key)
return 0, easy.TypeNull, nil, err
}
size = v.Len()
if size == 0 {
return 0, easy.TypeNull, nil, errNoData
}
//获取数组内的数据类型
typ := v.Type()
typ = typ.Elem()
if typ.Kind() == reflect.Ptr {
typ = typ.Elem()
}
typ = typ.FieldByIndex(ids).Type
//log.Println(typ.Name(), "==>", typ.Kind())
valueType = easy.GetReflectType(typ)
if valueType == easy.TypeNull {
err = errors.New("值类型是NULL")
return 0, easy.TypeNull, nil, err
}
return
}
/**
* @description: 前置条件的验证
* @param {reflect.Value} v
* @param {string} key
* @param {bool} setError
* @return {*}
*/
func (m *Table) checkPreconditionsOr(v reflect.Value, key string) (size int, valueType byte, ids []int, err error) {
ids, ok := m.key[key]
if !ok {
err = errors.New("没有此列名" + key)
return 0, easy.TypeNull, nil, err
}
if !v.IsValid() {
return 0, easy.TypeNull, nil, errNoData
}
size = v.Len()
if size == 0 {
return 0, easy.TypeNull, nil, errNoData
}
//获取数组内的数据类型
typ := v.Type()
typ = typ.Elem()
if typ.Kind() == reflect.Ptr {
typ = typ.Elem()
}
typ = typ.FieldByIndex(ids).Type
//log.Println(typ.Name(), "==>", typ.Kind())
valueType = easy.GetReflectType(typ)
if valueType == easy.TypeNull {
err = errors.New("值类型是NULL")
return 0, easy.TypeNull, nil, err
}
return
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/haodreams/query.git
git@gitee.com:haodreams/query.git
haodreams
query
query
97e1fcd00b97

搜索帮助