From 0651e60d6757d4d33771e937ac9b575fc4827771 Mon Sep 17 00:00:00 2001 From: glennliao Date: Mon, 6 Mar 2023 09:43:21 +0800 Subject: [PATCH] just run ok --- .gitignore | 3 +- action/action.go | 19 ++- action/node.go | 20 +-- apijson.go | 8 +- config/access.go | 2 + config/access_config.go | 98 +++++++++++ config/config.go | 27 ++- config/db/access.go | 174 -------------------- config/db/table.go | 65 -------- config/dbmeta.go | 42 +++++ config/executor/query.go | 15 +- config/field.go | 34 ---- config/{functions => }/functions.go | 28 ++-- config/{db/request.go => request_config.go} | 31 ++-- config/tables/table.go | 2 +- consts/errors.go | 18 ++ drivers/executor_goframe/query.go | 52 +++--- drivers/framework_goframe/gf.go | 23 ++- drivers/framework_goframe/mode.go | 10 +- go.mod | 12 +- go.sum | 48 +++++- query/node.go | 21 ++- query/query.go | 12 ++ query/util.go | 3 +- test/tt/z_test.go | 29 ++++ test/z_app_test.go | 24 +++ test/z_main_test.go | 90 +++++++++- 27 files changed, 522 insertions(+), 388 deletions(-) create mode 100644 config/access_config.go delete mode 100644 config/db/access.go delete mode 100644 config/db/table.go create mode 100644 config/dbmeta.go rename config/{functions => }/functions.go (55%) rename config/{db/request.go => request_config.go} (78%) create mode 100644 consts/errors.go create mode 100644 test/tt/z_test.go diff --git a/.gitignore b/.gitignore index d7c3743..4973e41 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ .idea -*.exe \ No newline at end of file +*.exe +*.sqlite3 \ No newline at end of file diff --git a/action/action.go b/action/action.go index 5ed1360..762009f 100644 --- a/action/action.go +++ b/action/action.go @@ -3,7 +3,6 @@ package action import ( "context" "github.com/glennliao/apijson-go/config" - "github.com/glennliao/apijson-go/config/db" "github.com/glennliao/apijson-go/consts" "github.com/glennliao/apijson-go/model" "github.com/gogf/gf/v2/database/gdb" @@ -16,7 +15,7 @@ import ( // Action 非get查询的request表中的请求 type Action struct { ctx context.Context - tagRequest *db.Request + tagRequest *config.Request method string req model.Map @@ -32,11 +31,19 @@ type Action struct { NoRequestVerify bool Access *config.Access + + // dbFieldStyle 数据库字段命名风格 请求传递到数据库中 + DbFieldStyle config.FieldStyle + + // jsonFieldStyle 数据库返回的字段 + JsonFieldStyle config.FieldStyle + + Functions *config.Functions } -func New(ctx context.Context, method string, req model.Map) *Action { +func New(ctx context.Context, method string, req model.Map, requestCfg *config.RequestConfig) *Action { - request, err := checkTag(req, method) + request, err := checkTag(req, method, requestCfg) if err != nil { panic(err) } @@ -150,7 +157,7 @@ func (a *Action) Result() (model.Map, error) { return ret, err } -func checkTag(req model.Map, method string) (*db.Request, error) { +func checkTag(req model.Map, method string, requestCfg *config.RequestConfig) (*config.Request, error) { _tag, ok := req["tag"] if !ok { return nil, gerror.New("tag 缺失") @@ -159,7 +166,7 @@ func checkTag(req model.Map, method string) (*db.Request, error) { tag := gconv.String(_tag) version := req["version"] - request, err := db.GetRequest(tag, method, gconv.String(version)) + request, err := requestCfg.GetRequest(tag, method, gconv.String(version)) if err != nil { return nil, err } diff --git a/action/node.go b/action/node.go index 6928029..8904699 100644 --- a/action/node.go +++ b/action/node.go @@ -3,9 +3,7 @@ package action import ( "context" "github.com/glennliao/apijson-go/config" - "github.com/glennliao/apijson-go/config/db" "github.com/glennliao/apijson-go/config/executor" - "github.com/glennliao/apijson-go/config/functions" "github.com/glennliao/apijson-go/consts" "github.com/glennliao/apijson-go/model" "github.com/glennliao/apijson-go/util" @@ -27,7 +25,7 @@ type Node struct { Where []model.Map // 条件 RowKey string // 主键 - structure *db.Structure + structure *config.Structure executor string keyNode map[string]*Node @@ -35,7 +33,7 @@ type Node struct { access *config.Access } -func newNode(key string, req []model.Map, structure *db.Structure, executor string) Node { +func newNode(key string, req []model.Map, structure *config.Structure, executor string) Node { return Node{ Key: key, req: req, structure: structure, executor: executor, } @@ -54,7 +52,7 @@ func (n *Node) parseReq(method string) { if key == consts.Role { n.Role = util.String(val) } else { - key = config.GetDbFieldStyle()(n.ctx, n.TableName, key) + key = n.action.DbFieldStyle(n.ctx, n.TableName, key) if method == http.MethodDelete { n.Where[i][key] = val @@ -82,7 +80,7 @@ func (n *Node) parse(ctx context.Context, method string) error { if strings.HasSuffix(key, consts.ListKeySuffix) { key = key[0 : len(key)-2] } - access, err := db.GetAccess(key, true) + access, err := n.access.GetAccess(key, true) if err != nil { return err @@ -245,7 +243,7 @@ func (n *Node) reqUpdate() error { } } k := key[0 : len(key)-2] - val, err := functions.Call(n.ctx, functionName, param) + val, err := n.action.Functions.Call(n.ctx, functionName, param) if err != nil { return err } @@ -278,9 +276,9 @@ func (n *Node) reqUpdateBeforeDo() error { if strings.HasSuffix(k, consts.RefKeySuffix) { refNodeKey, refCol := util.ParseRefCol(v.(string)) if strings.HasSuffix(refNodeKey, consts.ListKeySuffix) { // 双列表 - n.Data[i][k] = n.keyNode[refNodeKey].Data[i][config.GetDbFieldStyle()(n.ctx, n.TableName, refCol)] + n.Data[i][k] = n.keyNode[refNodeKey].Data[i][n.action.DbFieldStyle(n.ctx, n.TableName, refCol)] } else { - n.Data[i][k] = n.keyNode[refNodeKey].Data[0][config.GetDbFieldStyle()(n.ctx, n.TableName, refCol)] + n.Data[i][k] = n.keyNode[refNodeKey].Data[0][n.action.DbFieldStyle(n.ctx, n.TableName, refCol)] } } } @@ -303,7 +301,7 @@ func (n *Node) do(ctx context.Context, method string, dataIndex int) (ret model. var rowKeyVal model.Map - access, err := db.GetAccess(n.Key, true) + access, err := n.access.GetAccess(n.Key, true) if err != nil { return nil, err } @@ -343,7 +341,7 @@ func (n *Node) do(ctx context.Context, method string, dataIndex int) (ret model. if len(n.Data) > 0 { //多条插入时返回值已经应该无意义了 - jsonStyle := config.GetJsonFieldStyle() + jsonStyle := n.action.JsonFieldStyle if rowKeyVal != nil { for k, v := range rowKeyVal { if k == consts.RowKey { diff --git a/apijson.go b/apijson.go index 022d2dd..4e1d304 100644 --- a/apijson.go +++ b/apijson.go @@ -28,8 +28,12 @@ func New() *ApiJson { } // Load load for defaultApiJson, 简化使用 -func Load(app func(ctx context.Context, a *ApiJson)) *ApiJson { - DefaultApiJson.Use(app) +func Load(apps ...func(ctx context.Context, a *ApiJson)) *ApiJson { + + for _, app := range apps { + DefaultApiJson.Use(app) + } + DefaultApiJson.Load() return DefaultApiJson } diff --git a/config/access.go b/config/access.go index 7d28809..ad285c5 100644 --- a/config/access.go +++ b/config/access.go @@ -63,6 +63,8 @@ type Access struct { DefaultRoleFunc DefaultRole roleList []string + + accessConfigMap map[string]AccessConfig } func NewAccess() *Access { diff --git a/config/access_config.go b/config/access_config.go new file mode 100644 index 0000000..240aab0 --- /dev/null +++ b/config/access_config.go @@ -0,0 +1,98 @@ +package config + +import ( + "github.com/glennliao/apijson-go/util" + "github.com/gogf/gf/v2/errors/gerror" + "github.com/gogf/gf/v2/os/gtime" + "github.com/samber/lo" + "net/http" +) + +type FieldsGetValue struct { + In map[string][]string + Out map[string]string +} + +type AccessConfig struct { + Debug int8 + Name string + Alias string + Get []string + Head []string + Gets []string + Heads []string + Post []string + Put []string + Delete []string + CreatedAt *gtime.Time + Detail string + + RowKeyGen string // 主键生成策略 + RowKey string + FieldsGet map[string]FieldsGetValue + Executor string +} + +func (a *AccessConfig) GetFieldsGetOutByRole(role string) []string { + var fieldsMap map[string]string + + if val, exists := a.FieldsGet[role]; exists { + fieldsMap = val.Out + } else { + fieldsMap = a.FieldsGet["default"].Out + } + return lo.Keys(fieldsMap) +} + +func (a *AccessConfig) GetFieldsGetInByRole(role string) map[string][]string { + var inFieldsMap map[string][]string + + if val, exists := a.FieldsGet[role]; exists { + inFieldsMap = val.In + } else { + inFieldsMap = a.FieldsGet["default"].In + } + + return inFieldsMap +} + +func (a *Access) GetAccess(tableAlias string, accessVerify bool) (*AccessConfig, error) { + tableAlias, _ = util.ParseNodeKey(tableAlias) + access, ok := a.accessConfigMap[tableAlias] + + if !ok { + if accessVerify { + return nil, gerror.Newf("access[%s]: 404", tableAlias) + } + return &AccessConfig{ + Debug: 0, + Name: tableAlias, + Alias: tableAlias, + }, nil + } + + return &access, nil +} + +func (a *Access) GetAccessRole(table string, method string) ([]string, string, error) { + access, ok := a.accessConfigMap[table] + + if !ok { + return nil, "", gerror.Newf("access[%s]: 404", table) + } + + switch method { + case http.MethodGet: + return access.Get, access.Name, nil + case http.MethodHead: + return access.Head, access.Name, nil + case http.MethodPost: + return access.Post, access.Name, nil + case http.MethodPut: + return access.Put, access.Name, nil + case http.MethodDelete: + return access.Delete, access.Name, nil + } + + return []string{}, access.Name, nil +} diff --git a/config/config.go b/config/config.go index 912e4af..e8cc30b 100644 --- a/config/config.go +++ b/config/config.go @@ -1,10 +1,26 @@ package config type Config struct { - Access *Access - MaxTreeWidth int - MaxTreeDeep int + Access *Access + + Functions *Functions + + MaxTreeWidth int + MaxTreeDeep int + rowKeyGenFuncMap map[string]RowKeyGenFuncHandler + + // dbFieldStyle 数据库字段命名风格 请求传递到数据库中 + DbFieldStyle FieldStyle + + // jsonFieldStyle 数据库返回的字段 + JsonFieldStyle FieldStyle + + DbMeta *DBMeta + + AccessList []AccessConfig // todo to access + + RequestConfig *RequestConfig } func New() *Config { @@ -16,5 +32,10 @@ func New() *Config { a.rowKeyGenFuncMap = make(map[string]RowKeyGenFuncHandler) + a.DbFieldStyle = CaseSnake + a.JsonFieldStyle = CaseCamel + + a.Functions = &Functions{} + return a } diff --git a/config/db/access.go b/config/db/access.go deleted file mode 100644 index ff2a4b2..0000000 --- a/config/db/access.go +++ /dev/null @@ -1,174 +0,0 @@ -package db - -import ( - "github.com/glennliao/apijson-go/config" - "github.com/glennliao/apijson-go/util" - "github.com/gogf/gf/v2/errors/gerror" - "github.com/gogf/gf/v2/frame/g" - "github.com/gogf/gf/v2/os/gtime" - "github.com/samber/lo" - "net/http" - "strings" -) - -var accessMap = map[string]Access{} - -type FieldsGetValue struct { - In map[string][]string - Out map[string]string -} - -type Access struct { - Debug int8 - Name string - Alias string - Get []string - Head []string - Gets []string - Heads []string - Post []string - Put []string - Delete []string - CreatedAt *gtime.Time - Detail string - - RowKeyGen string // 主键生成策略 - RowKey string - FieldsGet map[string]FieldsGetValue - Executor string -} - -func (a *Access) GetFieldsGetOutByRole(role string) []string { - var fieldsMap map[string]string - - if val, exists := a.FieldsGet[role]; exists { - fieldsMap = val.Out - } else { - fieldsMap = a.FieldsGet["default"].Out - } - return lo.Keys(fieldsMap) -} - -func (a *Access) GetFieldsGetInByRole(role string) map[string][]string { - var inFieldsMap map[string][]string - - if val, exists := a.FieldsGet[role]; exists { - inFieldsMap = val.In - } else { - inFieldsMap = a.FieldsGet["default"].In - } - - return inFieldsMap -} - -func loadAccessMap() { - _accessMap := make(map[string]Access) - - var accessList []Access - - db := g.DB() - - err := db.Model(config.TableAccess).Scan(&accessList) - if err != nil { - panic(err) - } - - type AccessExt struct { - RowKey string - FieldsGet map[string]FieldsGetValue - } - - for _, access := range accessList { - name := access.Alias - if name == "" { - name = access.Name - } - - if len(access.Get) > 0 { - access.Get = strings.Split(access.Get[0], ",") - } - if len(access.Head) > 0 { - access.Head = strings.Split(access.Head[0], ",") - } - if len(access.Gets) > 0 { - access.Gets = strings.Split(access.Gets[0], ",") - } - if len(access.Heads) > 0 { - access.Heads = strings.Split(access.Heads[0], ",") - } - if len(access.Post) > 0 { - access.Post = strings.Split(access.Post[0], ",") - } - if len(access.Put) > 0 { - access.Put = strings.Split(access.Put[0], ",") - } - if len(access.Delete) > 0 { - access.Delete = strings.Split(access.Delete[0], ",") - } - - _accessMap[name] = access - } - - accessMap = _accessMap -} - -func GetAccess(tableAlias string, accessVerify bool) (*Access, error) { - tableAlias, _ = util.ParseNodeKey(tableAlias) - access, ok := accessMap[tableAlias] - - if !ok { - if accessVerify { - return nil, gerror.Newf("access[%s]: 404", tableAlias) - } - return &Access{ - Debug: 0, - Name: tableAlias, - Alias: tableAlias, - }, nil - } - - return &access, nil -} - -func GetAccessRole(table string, method string) ([]string, string, error) { - access, ok := accessMap[table] - - if !ok { - return nil, "", gerror.Newf("access[%s]: 404", table) - } - - switch method { - case http.MethodGet: - return access.Get, access.Name, nil - case http.MethodHead: - return access.Head, access.Name, nil - case http.MethodPost: - return access.Post, access.Name, nil - case http.MethodPut: - return access.Put, access.Name, nil - case http.MethodDelete: - return access.Delete, access.Name, nil - } - - return []string{}, access.Name, nil -} - -func Init() { - - initTable() - - Reload() -} - -// Reload 重载刷新配置 -func Reload() { - loadAccessMap() - loadRequestMap() - loadTableMeta() -} - -// initTable 暂时先这样吧 -func initTable() { - // maybe need the sql file when not use table-sync - -} diff --git a/config/db/table.go b/config/db/table.go deleted file mode 100644 index c1dafd9..0000000 --- a/config/db/table.go +++ /dev/null @@ -1,65 +0,0 @@ -package db - -import ( - "context" - "github.com/gogf/gf/v2/frame/g" - "github.com/samber/lo" -) - -type ( - Column struct { - // 字段名 - Name string - } - - Table struct { - // 表名 - Name string - Columns []Column - } -) - -var tableMap = map[string]Table{} - -func GetTableColumns(tableName string) (columns []string) { - for _, column := range tableMap[tableName].Columns { - columns = append(columns, column.Name) - } - return -} - -func GetTableNameList() []string { - return lo.Keys(tableMap) -} - -func loadTableMeta() { - var ctx = context.TODO() - - db := g.DB() - - _tableMap := make(map[string]Table) - - tables, err := db.Tables(ctx) - if err != nil { - panic(err) - } - - for _, table := range tables { - fields, err := db.TableFields(ctx, table) - if err != nil { - panic(err) - } - - var columns []Column - for field, _ := range fields { - columns = append(columns, Column{Name: field}) - } - - _tableMap[table] = Table{ - Name: table, - Columns: columns, - } - } - - tableMap = _tableMap -} diff --git a/config/dbmeta.go b/config/dbmeta.go new file mode 100644 index 0000000..f8fb2f4 --- /dev/null +++ b/config/dbmeta.go @@ -0,0 +1,42 @@ +package config + +import "github.com/samber/lo" + +type ( + Column struct { + // 字段名 + Name string + } + + Table struct { + // 表名 + Name string + Columns []Column + } +) + +type DBMeta struct { + tableMap map[string]Table +} + +func NewDbMeta(tables []Table) *DBMeta { + d := &DBMeta{} + d.tableMap = make(map[string]Table) + + for _, table := range tables { + d.tableMap[table.Name] = table + } + + return d +} + +func (d *DBMeta) GetTableColumns(tableName string) (columns []string) { + for _, column := range d.tableMap[tableName].Columns { + columns = append(columns, column.Name) + } + return +} + +func (d *DBMeta) GetTableNameList() []string { + return lo.Keys(d.tableMap) +} diff --git a/config/executor/query.go b/config/executor/query.go index adc204b..b1bbd34 100644 --- a/config/executor/query.go +++ b/config/executor/query.go @@ -2,7 +2,7 @@ package executor import ( "context" - "github.com/glennliao/apijson-go/config/db" + "github.com/glennliao/apijson-go/config" "github.com/glennliao/apijson-go/model" "github.com/samber/lo" ) @@ -10,12 +10,13 @@ import ( type QueryExecutor interface { ParseCondition(conditions model.MapStrAny, accessVerify bool) error ParseCtrl(ctrl model.Map) error - List(page int, count int, needTotal bool) (list []model.Map, total int64, err error) + List(page int, count int) (list []model.Map, err error) + Count() (total int64, err error) One() (model.Map, error) - EmptyResult() + SetEmptyResult() } -type queryExecutorBuilder func(ctx context.Context, noAccessVerify bool, role string, access *db.Access) (QueryExecutor, error) +type queryExecutorBuilder func(ctx context.Context, noAccessVerify bool, role string, access *config.AccessConfig, config *config.Config) (QueryExecutor, error) var queryExecutorBuilderMap = map[string]queryExecutorBuilder{} @@ -23,11 +24,11 @@ func RegQueryExecutor(name string, e queryExecutorBuilder) { queryExecutorBuilderMap[name] = e } -func NewQueryExecutor(name string, ctx context.Context, noAccessVerify bool, role string, access *db.Access) (QueryExecutor, error) { +func NewQueryExecutor(name string, ctx context.Context, noAccessVerify bool, role string, access *config.AccessConfig, config *config.Config) (QueryExecutor, error) { if v, exists := queryExecutorBuilderMap[name]; exists { - return v(ctx, noAccessVerify, role, access) + return v(ctx, noAccessVerify, role, access, config) } - return queryExecutorBuilderMap["default"](ctx, noAccessVerify, role, access) + return queryExecutorBuilderMap["default"](ctx, noAccessVerify, role, access, config) } func QueryExecutorList() []string { diff --git a/config/field.go b/config/field.go index a3d65d6..b08d267 100644 --- a/config/field.go +++ b/config/field.go @@ -5,8 +5,6 @@ import ( "github.com/gogf/gf/v2/text/gstr" ) -// ========================= 字段配置 ======================= - type FieldStyle func(ctx context.Context, table string, column string) string func CaseCamel(ctx context.Context, table string, column string) string { @@ -24,35 +22,3 @@ func CaseSnake(ctx context.Context, table string, column string) string { func Ori(ctx context.Context, table string, column string) string { return column } - -// jsonFieldStyle 数据库返回的字段 -var jsonFieldStyleFunc FieldStyle = CaseCamel - -// dbFieldStyle 数据库字段命名风格 请求传递到数据库中 -var dbFieldStyleFunc = CaseSnake - -// SetJsonFieldStyle 设置返回的 json字段风格, -func SetJsonFieldStyle(style FieldStyle) { - jsonFieldStyleFunc = style -} - -// SetDbFieldStyle 设置数据库的字段风格 -func SetDbFieldStyle(style FieldStyle) { - dbFieldStyleFunc = style -} - -// GetJsonFieldStyle 设置返回的 json字段风格, -func GetJsonFieldStyle() FieldStyle { - if jsonFieldStyleFunc == nil { - return Ori - } - return jsonFieldStyleFunc -} - -// GetDbFieldStyle 设置数据库的字段风格 -func GetDbFieldStyle() FieldStyle { - if dbFieldStyleFunc == nil { - return Ori - } - return dbFieldStyleFunc -} diff --git a/config/functions/functions.go b/config/functions.go similarity index 55% rename from config/functions/functions.go rename to config/functions.go index df7e260..d707b97 100644 --- a/config/functions/functions.go +++ b/config/functions.go @@ -1,35 +1,39 @@ -package functions +package config import ( "context" "fmt" + "github.com/glennliao/apijson-go/model" "github.com/gogf/gf/v2/frame/g" ) type Func struct { - Handler func(ctx context.Context, param g.Map) (res any, err error) + Handler func(ctx context.Context, param model.Map) (res any, err error) } -var funcMap = make(map[string]Func) +type Functions struct { + funcMap map[string]Func +} -func Reg(name string, f Func) { - if _, exists := funcMap[name]; exists { +func (f *Functions) Bind(name string, _func Func) { + if _, exists := f.funcMap[name]; exists { panic(fmt.Errorf(" function %s has exists", name)) } - funcMap[name] = f + f.funcMap[name] = _func } -func RegHandler(name string, handler func(ctx context.Context, param g.Map) (res any, err error)) { - if _, exists := funcMap[name]; exists { +// ? +func (f *Functions) BindHandlerFunc(name string, handler func(ctx context.Context, param model.Map) (res any, err error)) { + if _, exists := f.funcMap[name]; exists { panic(fmt.Errorf(" function %s has exists", name)) } - funcMap[name] = struct { - Handler func(ctx context.Context, param g.Map) (res any, err error) + f.funcMap[name] = struct { + Handler func(ctx context.Context, param model.Map) (res any, err error) }{Handler: handler} } -func Call(ctx context.Context, name string, param g.Map) (any, error) { - return funcMap[name].Handler(ctx, param) +func (f *Functions) Call(ctx context.Context, name string, param g.Map) (any, error) { + return f.funcMap[name].Handler(ctx, param) } // functions 提供的功能 diff --git a/config/db/request.go b/config/request_config.go similarity index 78% rename from config/db/request.go rename to config/request_config.go index 95119e5..502d464 100644 --- a/config/db/request.go +++ b/config/request_config.go @@ -1,7 +1,6 @@ -package db +package config import ( - "github.com/glennliao/apijson-go/config" "github.com/glennliao/apijson-go/consts" "github.com/gogf/gf/v2/errors/gerror" "github.com/gogf/gf/v2/frame/g" @@ -10,8 +9,6 @@ import ( "strings" ) -var requestMap = map[string]*Request{} - type Request struct { Debug int8 Version int16 @@ -42,14 +39,13 @@ type Structure struct { Remove []string `json:"REMOVE,omitempty"` } -func loadRequestMap() { - _requestMap := make(map[string]*Request) +type RequestConfig struct { + requestMap map[string]*Request +} - var requestList []Request - err := g.DB().Model(config.TableRequest).OrderAsc("version").Scan(&requestList) - if err != nil { - panic(err) - } +func NewRequestConfig(requestList []Request) *RequestConfig { + c := RequestConfig{} + requestMap := make(map[string]*Request) for _, _item := range requestList { item := _item @@ -67,7 +63,7 @@ func loadRequestMap() { item.Structure = make(map[string]*Structure) for k, v := range item.StructureDb { structure := Structure{} - err = gconv.Scan(v, &structure) + err := gconv.Scan(v, &structure) if err != nil { panic(err) } @@ -88,12 +84,13 @@ func loadRequestMap() { item.ExecQueue = []string{tag} } - _requestMap[getRequestFullKey(item.Tag, item.Method, gconv.String(item.Version))] = &item + requestMap[getRequestFullKey(item.Tag, item.Method, gconv.String(item.Version))] = &item // 获取时version排序,所以此处最后一个为最新 - _requestMap[getRequestFullKey(item.Tag, item.Method, "latest")] = &item + requestMap[getRequestFullKey(item.Tag, item.Method, "latest")] = &item } - requestMap = _requestMap + c.requestMap = requestMap + return &c } func getTag(tag string) (name string, isList bool) { @@ -111,14 +108,14 @@ func getRequestFullKey(tag string, method string, version string) string { return tag + "@" + method + "@" + version } -func GetRequest(tag string, method string, version string) (*Request, error) { +func (c *RequestConfig) GetRequest(tag string, method string, version string) (*Request, error) { if version == "" || version == "-1" || version == "0" { version = "latest" } key := getRequestFullKey(tag, method, version) - request, ok := requestMap[key] + request, ok := c.requestMap[key] if !ok { return nil, gerror.Newf("request[%s]: 404", key) diff --git a/config/tables/table.go b/config/tables/table.go index a0b1627..bcb368c 100644 --- a/config/tables/table.go +++ b/config/tables/table.go @@ -32,7 +32,7 @@ type Request struct { Debug int8 `ddl:"not null;default:0;comment:是否调试,开发环境可用"` Tag string `ddl:"not null;size:32;not null;comment:标签名(表别名)"` Version string `ddl:"not null;size:8;comment:版本号"` - Method string `ddl:"not null;size:5;comment:请求方式"` + Method string `ddl:"not null;size:6;comment:请求方式"` Structure map[string]any `ddl:"not null;type:json;comment:请求结构"` Detail string `ddl:"size:512;comment:描述说明"` CreatedAt *time.Time `ddl:"NOT NULL;comment:创建时间"` diff --git a/consts/errors.go b/consts/errors.go new file mode 100644 index 0000000..93290a9 --- /dev/null +++ b/consts/errors.go @@ -0,0 +1,18 @@ +package consts + +const ( + ErrCode = 40001 +) + +type Err struct { + code int + message string +} + +func (e *Err) Code() int { + return e.code +} + +func (e *Err) Error() string { + return e.message +} diff --git a/drivers/executor_goframe/query.go b/drivers/executor_goframe/query.go index a934548..7238f16 100644 --- a/drivers/executor_goframe/query.go +++ b/drivers/executor_goframe/query.go @@ -3,7 +3,6 @@ package executor_goframe import ( "context" "github.com/glennliao/apijson-go/config" - "github.com/glennliao/apijson-go/config/db" "github.com/glennliao/apijson-go/config/executor" "github.com/glennliao/apijson-go/consts" "github.com/glennliao/apijson-go/model" @@ -34,10 +33,12 @@ type SqlExecutor struct { noAccessVerify bool - access *db.Access + access *config.AccessConfig + + config *config.Config } -func New(ctx context.Context, noAccessVerify bool, role string, access *db.Access) (executor.QueryExecutor, error) { +func New(ctx context.Context, noAccessVerify bool, role string, access *config.AccessConfig, config *config.Config) (executor.QueryExecutor, error) { return &SqlExecutor{ ctx: ctx, @@ -49,6 +50,7 @@ func New(ctx context.Context, noAccessVerify bool, role string, access *db.Acces WithEmptyResult: false, noAccessVerify: noAccessVerify, access: access, + config: config, }, nil } @@ -85,7 +87,7 @@ func (e *SqlExecutor) ParseCondition(conditions model.MapStrAny, accessVerify bo inFieldsMap := e.access.GetFieldsGetInByRole(e.Role) - dbStyle := config.GetDbFieldStyle() + dbStyle := e.config.DbFieldStyle tableName := e.access.Name @@ -166,7 +168,7 @@ var exp = regexp.MustCompile(`^[\s\w][\w()]+`) // 匹配 field, COUNT(field) // ParseCtrl 解析 @column,@group等控制类 func (e *SqlExecutor) ParseCtrl(ctrl model.Map) error { - fieldStyle := config.GetDbFieldStyle() + fieldStyle := e.config.DbFieldStyle tableName := e.access.Name for k, v := range ctrl { // 使用;分割字段 @@ -210,7 +212,7 @@ func (e *SqlExecutor) build() *gdb.Model { whereBuild := m.Builder() - fieldStyle := config.GetDbFieldStyle() + fieldStyle := e.config.DbFieldStyle for _, whereItem := range e.Where { key := fieldStyle(e.ctx, tableName, whereItem[0].(string)) @@ -279,13 +281,13 @@ func (e *SqlExecutor) column() []string { if e.Columns != nil { columns = e.Columns } else { - columns = db.GetTableColumns(tableName) + columns = e.config.DbMeta.GetTableColumns(tableName) } var fields = make([]string, 0, len(columns)) - fieldStyle := config.GetJsonFieldStyle() - dbStyle := config.GetDbFieldStyle() + fieldStyle := e.config.JsonFieldStyle + dbStyle := e.config.DbFieldStyle for _, column := range columns { fieldName := column @@ -311,41 +313,45 @@ func (e *SqlExecutor) column() []string { return fields } -func (e *SqlExecutor) EmptyResult() { +func (e *SqlExecutor) SetEmptyResult() { e.WithEmptyResult = true } -func (e *SqlExecutor) List(page int, count int, needTotal bool) (list []model.Map, total int64, err error) { +func (e *SqlExecutor) Count() (total int64, err error) { + m := e.build() + _total, err := m.Count() + if err != nil || _total == 0 { + return 0, err + } else { + total = int64(_total) + } + + return total, nil + +} + +func (e *SqlExecutor) List(page int, count int) (list []model.Map, err error) { if e.WithEmptyResult { - return nil, 0, err + return nil, err } m := e.build() - if needTotal { - _total, err := m.Count() - if err != nil || _total == 0 { - return nil, 0, err - } else { - total = int64(_total) - } - } - m = m.Fields(e.column()) m = m.Page(page, count) all, err := m.All() if err != nil { - return nil, 0, err + return nil, err } for _, item := range all.List() { list = append(list, item) } - return list, total, nil + return list, nil } func (e *SqlExecutor) One() (model.Map, error) { diff --git a/drivers/framework_goframe/gf.go b/drivers/framework_goframe/gf.go index f8a1525..a43a438 100644 --- a/drivers/framework_goframe/gf.go +++ b/drivers/framework_goframe/gf.go @@ -59,6 +59,14 @@ func (gf *GF) Get(ctx context.Context, req model.Map) (res model.Map, err error) q.NoAccessVerify = gf.apijson.Config().Access.NoVerify q.Access = gf.apijson.Config().Access q.AccessCondition = gf.apijson.Config().Access.ConditionFunc + + q.DbMeta = gf.apijson.Config().DbMeta // todo + q.Functions = gf.apijson.Config().Functions // todo + q.DbFieldStyle = gf.apijson.Config().DbFieldStyle + q.JsonFieldStyle = gf.apijson.Config().JsonFieldStyle + + q.Config = gf.apijson.Config() + return q.Result() } @@ -67,20 +75,29 @@ func (gf *GF) Head(ctx context.Context, req model.Map) (res model.Map, err error } func (gf *GF) Post(ctx context.Context, req model.Map) (res model.Map, err error) { - act := action.New(ctx, http.MethodPost, req) + act := action.New(ctx, http.MethodPost, req, gf.apijson.Config().RequestConfig) act.NoAccessVerify = gf.apijson.Config().Access.NoVerify + act.DbFieldStyle = gf.apijson.Config().DbFieldStyle + act.JsonFieldStyle = gf.apijson.Config().JsonFieldStyle + act.Functions = gf.apijson.Config().Functions return act.Result() } func (gf *GF) Put(ctx context.Context, req model.Map) (res model.Map, err error) { - act := action.New(ctx, http.MethodPut, req) + act := action.New(ctx, http.MethodPut, req, gf.apijson.Config().RequestConfig) act.NoAccessVerify = gf.apijson.Config().Access.NoVerify + act.DbFieldStyle = gf.apijson.Config().DbFieldStyle + act.JsonFieldStyle = gf.apijson.Config().JsonFieldStyle + act.Functions = gf.apijson.Config().Functions return act.Result() } func (gf *GF) Delete(ctx context.Context, req model.Map) (res model.Map, err error) { - act := action.New(ctx, http.MethodDelete, req) + act := action.New(ctx, http.MethodDelete, req, gf.apijson.Config().RequestConfig) act.NoAccessVerify = gf.apijson.Config().Access.NoVerify + act.DbFieldStyle = gf.apijson.Config().DbFieldStyle + act.JsonFieldStyle = gf.apijson.Config().JsonFieldStyle + act.Functions = gf.apijson.Config().Functions return act.Result() } diff --git a/drivers/framework_goframe/mode.go b/drivers/framework_goframe/mode.go index 61124f2..ad56790 100644 --- a/drivers/framework_goframe/mode.go +++ b/drivers/framework_goframe/mode.go @@ -2,11 +2,11 @@ package framework_goframe import "github.com/gogf/gf/v2/container/gmap" -type Mode = func(data *gmap.ListMap, meta *gmap.ListMap) gmap.ListMap +type Mode = func(data *gmap.ListMap, meta *gmap.ListMap) *gmap.ListMap -func SpreadMode(data *gmap.ListMap, meta *gmap.ListMap) gmap.ListMap { +func SpreadMode(data *gmap.ListMap, meta *gmap.ListMap) *gmap.ListMap { - res := gmap.ListMap{} + res := &gmap.ListMap{} for _, k := range data.Keys() { res.Set(k, data.Get(k)) } @@ -17,8 +17,8 @@ func SpreadMode(data *gmap.ListMap, meta *gmap.ListMap) gmap.ListMap { return res } -func InDataMode(data *gmap.ListMap, meta *gmap.ListMap) gmap.ListMap { - res := gmap.ListMap{} +func InDataMode(data *gmap.ListMap, meta *gmap.ListMap) *gmap.ListMap { + res := &gmap.ListMap{} res.Set("data", data) for _, k := range meta.Keys() { res.Set(k, meta.Get(k)) diff --git a/go.mod b/go.mod index f02ecbc..9d538c4 100644 --- a/go.mod +++ b/go.mod @@ -1,8 +1,8 @@ module github.com/glennliao/apijson-go require ( - github.com/glennliao/table-sync v0.2.0 - github.com/gogf/gf/contrib/drivers/mysql/v2 v2.3.2 + github.com/glennliao/table-sync v0.2.1 + github.com/gogf/gf/contrib/drivers/sqlite/v2 v2.3.2 github.com/gogf/gf/v2 v2.3.2 github.com/iancoleman/orderedmap v0.2.0 github.com/samber/lo v1.33.0 @@ -13,9 +13,10 @@ require ( github.com/clbanning/mxj/v2 v2.5.5 // indirect github.com/fatih/color v1.13.0 // indirect github.com/fsnotify/fsnotify v1.5.4 // indirect + github.com/glebarez/go-sqlite v1.17.3 // indirect github.com/go-logr/logr v1.2.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect - github.com/go-sql-driver/mysql v1.6.0 // indirect + github.com/google/uuid v1.3.0 // indirect github.com/gorilla/websocket v1.5.0 // indirect github.com/grokify/html-strip-tags-go v0.0.1 // indirect github.com/magiconair/properties v1.8.6 // indirect @@ -23,6 +24,7 @@ require ( github.com/mattn/go-isatty v0.0.14 // indirect github.com/mattn/go-runewidth v0.0.9 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect + github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect go.opentelemetry.io/otel v1.7.0 // indirect go.opentelemetry.io/otel/sdk v1.7.0 // indirect go.opentelemetry.io/otel/trace v1.7.0 // indirect @@ -31,6 +33,10 @@ require ( golang.org/x/sys v0.1.0 // indirect golang.org/x/text v0.3.8-0.20211105212822-18b340fc7af2 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect + modernc.org/libc v1.16.8 // indirect + modernc.org/mathutil v1.4.1 // indirect + modernc.org/memory v1.1.1 // indirect + modernc.org/sqlite v1.17.3 // indirect ) go 1.18 diff --git a/go.sum b/go.sum index 0689698..abe08ab 100644 --- a/go.sum +++ b/go.sum @@ -8,6 +8,7 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= +github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= @@ -15,19 +16,20 @@ github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4 github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= -github.com/glennliao/table-sync v0.2.0 h1:uxkrgNcDHCA/G27qk00+FqF2a832VVXmFX+/5zRHSkQ= -github.com/glennliao/table-sync v0.2.0/go.mod h1:YgVRcaEqwZMQqjN0fuWqOCAo2vMkfbUE9OSXM6jgiYw= +github.com/glebarez/go-sqlite v1.17.3 h1:Rji9ROVSTTfjuWD6j5B+8DtkNvPILoUC3xRhkQzGxvk= +github.com/glebarez/go-sqlite v1.17.3/go.mod h1:Hg+PQuhUy98XCxWEJEaWob8x7lhJzhNYF1nZbUiRGIY= +github.com/glennliao/table-sync v0.2.1 h1:Z/7j4KJoDzrxIdE2GpaBx+qblYaymqH2+KZOAb5GJ0w= +github.com/glennliao/table-sync v0.2.1/go.mod h1:YgVRcaEqwZMQqjN0fuWqOCAo2vMkfbUE9OSXM6jgiYw= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-redis/redis/v8 v8.11.4/go.mod h1:2Z2wHZXdQpCDXEGzqMockDpNyYvi2l4Pxt6RJr792+w= -github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= -github.com/gogf/gf/contrib/drivers/mysql/v2 v2.3.2 h1:BZww6QOFgiN/YvovUtN64sgnq59TIg8vtkG8AL6eSl0= -github.com/gogf/gf/contrib/drivers/mysql/v2 v2.3.2/go.mod h1:z+/0qiOwMroAnj5ESuobTv0l5P83rf+XR3r6Fj8WJyk= +github.com/gogf/gf/contrib/drivers/sqlite/v2 v2.3.2 h1:tO9ThU69zo6y3G6KBQPgO0MR79ZfdA5HSYsfl73Marg= +github.com/gogf/gf/contrib/drivers/sqlite/v2 v2.3.2/go.mod h1:RL2xJ0ju5/an2zZj0SBT2KkrMtZ1QOWlpmfc8ZjwHcc= github.com/gogf/gf/v2 v2.0.0/go.mod h1:apktt6TleWtCIwpz63vBqUnw8MX8gWKoZyxgDpXFtgM= github.com/gogf/gf/v2 v2.3.2 h1:nlJ0zuDWqFb93/faZmr7V+GADx/lzz5Unz/9x6OJ2u8= github.com/gogf/gf/v2 v2.3.2/go.mod h1:tsbmtwcAl2chcYoq/fP9W2FZf06aw4i89X34nbSHo9Y= @@ -43,10 +45,13 @@ github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiu github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= @@ -55,6 +60,7 @@ github.com/grokify/html-strip-tags-go v0.0.1/go.mod h1:2Su6romC5/1VXOQMaWL2yb618 github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/iancoleman/orderedmap v0.2.0 h1:sq1N/TFpYH++aViPcaKjys3bDClUEU7s5B+z6jq8pNA= github.com/iancoleman/orderedmap v0.2.0/go.mod h1:N0Wam8K1arqPXNWjMo21EXnBPOPp36vB07FNRdD2geA= +github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo= github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= @@ -65,6 +71,7 @@ github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9 github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-sqlite3 v1.14.12/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= @@ -78,6 +85,8 @@ github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1y github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk= +github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/samber/lo v1.33.0 h1:2aKucr+rQV6gHpY3bpeZu69uYoQOzVhGT3J22Op6Cjk= github.com/samber/lo v1.33.0/go.mod h1:HLeWcJRRyLKp3+/XBJvOrerCQn9mhdKMHyd7IRlgeQ8= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -134,6 +143,8 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220405052023-b1e9470b6e64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -145,6 +156,7 @@ golang.org/x/text v0.3.8-0.20211105212822-18b340fc7af2 h1:GLw7MR8AfAG2GmGcmVgObF golang.org/x/text v0.3.8-0.20211105212822-18b340fc7af2/go.mod h1:EFNZuWvGYxIRUEX+K8UmCFwYmZjqcrnq15ZuVldZkZ0= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -171,3 +183,29 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +lukechampine.com/uint128 v1.1.1/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= +modernc.org/cc/v3 v3.36.0/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= +modernc.org/ccgo/v3 v3.0.0-20220428102840-41399a37e894/go.mod h1:eI31LL8EwEBKPpNpA4bU1/i+sKOwOrQy8D87zWUcRZc= +modernc.org/ccgo/v3 v3.0.0-20220430103911-bc99d88307be/go.mod h1:bwdAnOoaIt8Ax9YdWGjxWsdkPcZyRPHqrOvJxaKAKGw= +modernc.org/ccgo/v3 v3.16.4/go.mod h1:tGtX0gE9Jn7hdZFeU88slbTh1UtCYKusWOoCJuvkWsQ= +modernc.org/ccgo/v3 v3.16.6/go.mod h1:tGtX0gE9Jn7hdZFeU88slbTh1UtCYKusWOoCJuvkWsQ= +modernc.org/ccorpus v1.11.6/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ= +modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM= +modernc.org/libc v0.0.0-20220428101251-2d5f3daf273b/go.mod h1:p7Mg4+koNjc8jkqwcoFBJx7tXkpj00G77X7A72jXPXA= +modernc.org/libc v1.16.0/go.mod h1:N4LD6DBE9cf+Dzf9buBlzVJndKr/iJHG97vGLHYnb5A= +modernc.org/libc v1.16.1/go.mod h1:JjJE0eu4yeK7tab2n4S1w8tlWd9MxXLRzheaRnAKymU= +modernc.org/libc v1.16.7/go.mod h1:hYIV5VZczAmGZAnG15Vdngn5HSF5cSkbvfz2B7GRuVU= +modernc.org/libc v1.16.8 h1:Ux98PaOMvolgoFX/YwusFOHBnanXdGRmWgI8ciI2z4o= +modernc.org/libc v1.16.8/go.mod h1:hYIV5VZczAmGZAnG15Vdngn5HSF5cSkbvfz2B7GRuVU= +modernc.org/mathutil v1.2.2/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/mathutil v1.4.1 h1:ij3fYGe8zBF4Vu+g0oT7mB06r8sqGWKuJu1yXeR4by8= +modernc.org/mathutil v1.4.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/memory v1.1.1 h1:bDOL0DIDLQv7bWhP3gMvIrnoFw+Eo6F7a2QK9HPDiFU= +modernc.org/memory v1.1.1/go.mod h1:/0wo5ibyrQiaoUoH7f9D8dnglAmILJ5/cxZlRECf+Nw= +modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= +modernc.org/sqlite v1.17.3 h1:iE+coC5g17LtByDYDWKpR6m2Z9022YrSh3bumwOnIrI= +modernc.org/sqlite v1.17.3/go.mod h1:10hPVYar9C0kfXuTWGz8s0XtB8uAGymUy51ZzStYe3k= +modernc.org/strutil v1.1.1/go.mod h1:DE+MQQ/hjKBZS2zNInV5hhcipt5rLPWkmpbGeW5mmdw= +modernc.org/tcl v1.13.1/go.mod h1:XOLfOwzhkljL4itZkK6T72ckMgvj0BDsnKNdZVUOecw= +modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= +modernc.org/z v1.5.1/go.mod h1:eWFB510QWW5Th9YGZT81s+LwvaAs3Q2yr4sP0rmLkv8= diff --git a/query/node.go b/query/node.go index 92b2aae..46c7fdc 100644 --- a/query/node.go +++ b/query/node.go @@ -2,9 +2,7 @@ package query import ( "context" - "github.com/glennliao/apijson-go/config/db" "github.com/glennliao/apijson-go/config/executor" - "github.com/glennliao/apijson-go/config/functions" "github.com/glennliao/apijson-go/consts" "github.com/glennliao/apijson-go/model" "github.com/glennliao/apijson-go/util" @@ -109,7 +107,7 @@ func newNode(query *Query, key string, path string, nodeReq any) *Node { node.Type = NodeTypeStruct // 结构节点下应该必须存在查询节点 if query.NoAccessVerify == false { - if lo.Contains(db.GetTableNameList(), k) { + if lo.Contains(query.DbMeta.GetTableNameList(), k) { node.Type = NodeTypeQuery } } @@ -209,7 +207,7 @@ func (n *Node) parse() { case NodeTypeQuery: tableKey := parseTableKey(n.Key, n.Path) - access, err := db.GetAccess(tableKey, n.queryContext.NoAccessVerify) + access, err := n.queryContext.Access.GetAccess(tableKey, n.queryContext.NoAccessVerify) if err != nil { n.err = err return @@ -239,7 +237,7 @@ func (n *Node) parse() { accessWhereCondition = condition.Where() // todo } - queryExecutor, err := executor.NewQueryExecutor(access.Executor, n.ctx, n.queryContext.NoAccessVerify, n.role, access) + queryExecutor, err := executor.NewQueryExecutor(access.Executor, n.ctx, n.queryContext.NoAccessVerify, n.role, access, n.queryContext.Config) if err != nil { n.err = err return @@ -437,7 +435,7 @@ func (n *Node) fetch() { valList := getColList(list, refNode.column) if len(valList) == 0 { // 未查询到主表, 故当前不再查询 - n.executor.EmptyResult() + n.executor.SetEmptyResult() break } @@ -453,7 +451,7 @@ func (n *Node) fetch() { } else { if ret == nil { // 未查询到主表, 故当前不再查询 - n.executor.EmptyResult() + n.executor.SetEmptyResult() break } @@ -507,7 +505,8 @@ func (n *Node) fetch() { count = 0 } - n.ret, n.total, n.err = n.executor.List(page, count, n.needTotal) + n.ret, n.err = n.executor.List(page, count) + n.total, n.err = n.executor.Count() } else { n.ret, n.err = n.executor.One() } @@ -536,7 +535,7 @@ func (n *Node) fetch() { } } var err error - n.ret.([]model.Map)[i][k], err = functions.Call(n.ctx, functionName, param) + n.ret.([]model.Map)[i][k], err = n.queryContext.Functions.Call(n.ctx, functionName, param) if err != nil { panic(err) } @@ -552,7 +551,7 @@ func (n *Node) fetch() { } var err error - n.ret.(model.Map)[k], err = functions.Call(n.ctx, functionName, param) + n.ret.(model.Map)[k], err = n.queryContext.Functions.Call(n.ctx, functionName, param) if err != nil { panic(err) } @@ -580,7 +579,7 @@ func (n *Node) fetch() { param[key] = n.queryContext.pathNodes[key].simpleReqVal } - n.ret, n.err = functions.Call(n.ctx, functionName, param) + n.ret, n.err = n.queryContext.Functions.Call(n.ctx, functionName, param) } } diff --git a/query/query.go b/query/query.go index a04cbf5..4a05231 100644 --- a/query/query.go +++ b/query/query.go @@ -38,6 +38,18 @@ type Query struct { AccessCondition config.AccessCondition Access *config.Access + + DbMeta *config.DBMeta + + Functions *config.Functions + + // dbFieldStyle 数据库字段命名风格 请求传递到数据库中 + DbFieldStyle config.FieldStyle + + // jsonFieldStyle 数据库返回的字段 + JsonFieldStyle config.FieldStyle + + Config *config.Config } func New(ctx context.Context, req model.Map) *Query { diff --git a/query/util.go b/query/util.go index 3192edd..f8c994f 100644 --- a/query/util.go +++ b/query/util.go @@ -2,7 +2,6 @@ package query import ( "github.com/glennliao/apijson-go/config" - "github.com/glennliao/apijson-go/config/db" "github.com/glennliao/apijson-go/consts" "github.com/glennliao/apijson-go/model" "github.com/gogf/gf/v2/container/gset" @@ -56,7 +55,7 @@ func parseQueryNodeReq(reqMap model.Map, isList bool) (refMap model.MapStrStr, w } func hasAccess(node *Node, table string) (hasAccess bool, accessWhere *config.ConditionRet, err error) { - accessRoles, tableName, err := db.GetAccessRole(table, http.MethodGet) + accessRoles, tableName, err := node.queryContext.Access.GetAccessRole(table, http.MethodGet) if err != nil { return false, nil, err } diff --git a/test/tt/z_test.go b/test/tt/z_test.go new file mode 100644 index 0000000..0af63c1 --- /dev/null +++ b/test/tt/z_test.go @@ -0,0 +1,29 @@ +package tt + +import ( + "fmt" + "testing" +) + +type A struct { + Name string +} + +func (a *A) M() string { + return "A:" + a.Name +} + +type B struct { + A +} + +func test(a A) { + fmt.Print(a.M()) +} + +func TestName(t *testing.T) { + b := &B{} + + b.Name = "asdsad" + test(b.A) +} diff --git a/test/z_app_test.go b/test/z_app_test.go index e6e72c8..b81cdac 100644 --- a/test/z_app_test.go +++ b/test/z_app_test.go @@ -3,14 +3,38 @@ package main import ( "context" "github.com/glennliao/apijson-go" + "github.com/glennliao/apijson-go/config/tables" + "github.com/glennliao/table-sync/tablesync" + "github.com/gogf/gf/v2/frame/g" + "time" ) type User struct { + Id uint32 `ddl:"primaryKey"` + Username string + Password string + CreatedAt *time.Time + UpdatedAt *time.Time } type Todo struct { + Id uint32 `ddl:"primaryKey"` + UserId uint32 + Content string + CreatedAt *time.Time } func App(ctx context.Context, a *apijson.ApiJson) { + syncer := tablesync.Syncer{ + Tables: []tablesync.Table{ + User{}, Todo{}, + tables.Access{}, tables.Request{}, + }, + } + err := syncer.Sync(ctx, g.DB()) + if err != nil { + panic(err) + } + } diff --git a/test/z_main_test.go b/test/z_main_test.go index 18d6ff9..2a52590 100644 --- a/test/z_main_test.go +++ b/test/z_main_test.go @@ -1,7 +1,9 @@ package main import ( + "context" "github.com/glennliao/apijson-go" + "github.com/glennliao/apijson-go/config" _ "github.com/glennliao/apijson-go/drivers/executor/goframe" // need import for executor with goframe "github.com/glennliao/apijson-go/drivers/framework_goframe" "github.com/glennliao/apijson-go/model" @@ -9,13 +11,95 @@ import ( _ "github.com/gogf/gf/contrib/drivers/sqlite/v2" // need import for sqlite "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/os/gctx" + "strings" "testing" ) var a *apijson.ApiJson func init() { - a = apijson.Load(App) + a = apijson.Load(App, func(ctx context.Context, a *apijson.ApiJson) { + // access + var accessList []config.AccessConfig + + db := g.DB() + + err := db.Model("_access").Scan(&accessList) + if err != nil { + panic(err) + } + + for _, access := range accessList { + name := access.Alias + if name == "" { + name = access.Name + } + + if len(access.Get) > 0 { + access.Get = strings.Split(access.Get[0], ",") + } + if len(access.Head) > 0 { + access.Head = strings.Split(access.Head[0], ",") + } + if len(access.Gets) > 0 { + access.Gets = strings.Split(access.Gets[0], ",") + } + if len(access.Heads) > 0 { + access.Heads = strings.Split(access.Heads[0], ",") + } + if len(access.Post) > 0 { + access.Post = strings.Split(access.Post[0], ",") + } + if len(access.Put) > 0 { + access.Put = strings.Split(access.Put[0], ",") + } + if len(access.Delete) > 0 { + access.Delete = strings.Split(access.Delete[0], ",") + } + + accessList = append(accessList, access) + } + + a.Config().AccessList = accessList + + // request + var requestList []config.Request + err = g.DB().Model("_request").OrderAsc("version").Scan(&requestList) + if err != nil { + panic(err) + } + a.Config().RequestConfig = config.NewRequestConfig(requestList) + + // db meta + + var _tables []config.Table + + tables, err := db.Tables(ctx) + if err != nil { + panic(err) + } + + for _, table := range tables { + fields, err := db.TableFields(ctx, table) + if err != nil { + panic(err) + } + + var columns []config.Column + for field, _ := range fields { + columns = append(columns, config.Column{Name: field}) + } + + _tables = append(_tables, config.Table{ + Name: table, + Columns: columns, + }) + + } + + a.Config().DbMeta = config.NewDbMeta(_tables) + + }) } // notice: import section @@ -29,13 +113,13 @@ func TestQuery(t *testing.T) { ctx := gctx.New() q := query.New(ctx, model.Map{ - "t_user": model.Map{ + "user": model.Map{ "id": "123", "id{}": []string{"123", "456"}, "id>": "222", "@column": "id,userId", }, - "t_user[]": model.Map{ + "user[]": model.Map{ //"userId": "123", }, //"t_todo": model.Map{},