mirror of
https://gitee.com/johng/gf
synced 2026-06-06 16:21:40 +08:00
Merge remote-tracking branch 'origin/master' into feature/mssql
This commit is contained in:
@ -1,15 +1,30 @@
|
||||
# drivers
|
||||
Database drivers for package gdb.
|
||||
Powerful database drivers for package gdb.
|
||||
|
||||
# Installation
|
||||
Let's take `pgsql` for example.
|
||||
Let's take `mysql` for example.
|
||||
```
|
||||
go get -u github.com/gogf/gf/contrib/drivers/pgsql/v2
|
||||
go get -u github.com/gogf/gf/contrib/drivers/mysql/v2
|
||||
```
|
||||
|
||||
Choose and import the driver to your project:
|
||||
```
|
||||
import _ "github.com/gogf/gf/contrib/drivers/pgsql/v2"
|
||||
import _ "github.com/gogf/gf/contrib/drivers/mysql/v2"
|
||||
```
|
||||
|
||||
Commonly imported at top of `main.go`:
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
_ "github.com/gogf/gf/contrib/drivers/mysql/v2"
|
||||
|
||||
// Other imported packages.
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Main logics.
|
||||
}
|
||||
```
|
||||
|
||||
# Supported Drivers
|
||||
|
||||
@ -45,6 +45,8 @@ github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/ad
|
||||
github.com/grokify/html-strip-tags-go v0.0.1 h1:0fThFwLbW7P/kOiTBs03FsJSV9RM2M/Q/MOnCQxKMo0=
|
||||
github.com/grokify/html-strip-tags-go v0.0.1/go.mod h1:2Su6romC5/1VXOQMaWL2yb618ARB8iVo6/DR99A6d78=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo=
|
||||
github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
|
||||
github.com/mattn/go-colorable v0.1.9 h1:sqDoxXbdeALODt0DAeJCVp38ps9ZogZEAXjus69YV3U=
|
||||
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://github.com/gogf/gf.
|
||||
|
||||
package mssql
|
||||
package mssql_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
@ -18,7 +18,6 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
// 数据库对象/接口
|
||||
db gdb.DB
|
||||
dblink gdb.DB
|
||||
dbErr gdb.DB
|
||||
@ -110,10 +109,7 @@ func createTable(table ...string) (name string) {
|
||||
gtest.Fatal(err)
|
||||
}
|
||||
|
||||
// 选择操作数据库
|
||||
db.Schema("test")
|
||||
|
||||
//db.SetDebug(true)
|
||||
return
|
||||
}
|
||||
|
||||
@ -138,7 +134,6 @@ func createInitTable(table ...string) (name string) {
|
||||
return
|
||||
}
|
||||
|
||||
// 删除指定表.
|
||||
func dropTable(table string) {
|
||||
if _, err := db.Exec(context.Background(), fmt.Sprintf(`
|
||||
IF EXISTS (SELECT * FROM sysobjects WHERE name='%s' and xtype='U')
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://github.com/gogf/gf.
|
||||
|
||||
package mssql
|
||||
package mssql_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://github.com/gogf/gf.
|
||||
|
||||
package mssql
|
||||
package mssql_test
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
|
||||
@ -212,7 +212,7 @@ ORDER BY a.attnum`,
|
||||
Index: i,
|
||||
Name: m["field"].String(),
|
||||
Type: m["type"].String(),
|
||||
Null: m["null"].Bool(),
|
||||
Null: !m["null"].Bool(),
|
||||
Key: m["key"].String(),
|
||||
Default: m["default_value"].Val(),
|
||||
Comment: m["comment"].String(),
|
||||
|
||||
@ -28,6 +28,7 @@ type Command struct {
|
||||
Examples string // Usage examples.
|
||||
Additional string // Additional info about this command, which will be appended to the end of help info.
|
||||
Strict bool // Strict parsing options, which means it returns error if invalid option given.
|
||||
CaseSensitive bool // CaseSensitive parsing options, which means it parses input options in case-sensitive way.
|
||||
Config string // Config node name, which also retrieves the values from config component along with command line.
|
||||
parent *Command // Parent command for internal usage.
|
||||
commands []*Command // Sub commands of this command.
|
||||
|
||||
@ -9,11 +9,14 @@ package gcmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"github.com/gogf/gf/v2/container/gset"
|
||||
"github.com/gogf/gf/v2/encoding/gjson"
|
||||
"github.com/gogf/gf/v2/errors/gcode"
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
"github.com/gogf/gf/v2/internal/intlog"
|
||||
"github.com/gogf/gf/v2/internal/reflection"
|
||||
"github.com/gogf/gf/v2/internal/utils"
|
||||
"github.com/gogf/gf/v2/os/gstructs"
|
||||
@ -285,11 +288,17 @@ func newCommandFromMethod(object interface{}, method reflect.Value) (command *Co
|
||||
}
|
||||
// Construct input parameters.
|
||||
if len(data) > 0 {
|
||||
intlog.PrintFunc(ctx, func() string {
|
||||
return fmt.Sprintf(`input command data map: %s`, gjson.MustEncode(data))
|
||||
})
|
||||
if inputObject.Kind() == reflect.Ptr {
|
||||
err = gconv.Scan(data, inputObject.Interface())
|
||||
} else {
|
||||
err = gconv.Struct(data, inputObject.Addr().Interface())
|
||||
}
|
||||
intlog.PrintFunc(ctx, func() string {
|
||||
return fmt.Sprintf(`input object assigned data: %s`, gjson.MustEncode(inputObject.Interface()))
|
||||
})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
@ -146,7 +146,10 @@ func (c *Command) reParse(ctx context.Context, parser *Parser) (*Parser, error)
|
||||
}
|
||||
supportedOptions[optionKey] = !arg.Orphan
|
||||
}
|
||||
parser, err := Parse(supportedOptions, c.Strict)
|
||||
parser, err := Parse(supportedOptions, ParserOption{
|
||||
CaseSensitive: c.CaseSensitive,
|
||||
Strict: c.Strict,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@ -21,9 +21,15 @@ import (
|
||||
"github.com/gogf/gf/v2/text/gstr"
|
||||
)
|
||||
|
||||
// ParserOption manages the parsing options.
|
||||
type ParserOption struct {
|
||||
CaseSensitive bool // Marks options parsing in case-sensitive way.
|
||||
Strict bool // Whether stops parsing and returns error if invalid option passed.
|
||||
}
|
||||
|
||||
// Parser for arguments.
|
||||
type Parser struct {
|
||||
strict bool // Whether stops parsing and returns error if invalid option passed.
|
||||
option ParserOption // Parse option.
|
||||
parsedArgs []string // As name described.
|
||||
parsedOptions map[string]string // As name described.
|
||||
passedOptions map[string]bool // User passed supported options, like: map[string]bool{"name,n":true}
|
||||
@ -47,7 +53,7 @@ func ParserFromCtx(ctx context.Context) *Parser {
|
||||
// the value item of `supportedOptions` indicates whether corresponding option name needs argument or not.
|
||||
//
|
||||
// The optional parameter `strict` specifies whether stops parsing and returns error if invalid option passed.
|
||||
func Parse(supportedOptions map[string]bool, strict ...bool) (*Parser, error) {
|
||||
func Parse(supportedOptions map[string]bool, option ...ParserOption) (*Parser, error) {
|
||||
if supportedOptions == nil {
|
||||
command.Init(os.Args...)
|
||||
return &Parser{
|
||||
@ -55,7 +61,7 @@ func Parse(supportedOptions map[string]bool, strict ...bool) (*Parser, error) {
|
||||
parsedOptions: GetOptAll(),
|
||||
}, nil
|
||||
}
|
||||
return ParseArgs(os.Args, supportedOptions, strict...)
|
||||
return ParseArgs(os.Args, supportedOptions, option...)
|
||||
}
|
||||
|
||||
// ParseArgs creates and returns a new Parser with given arguments and supported options.
|
||||
@ -64,7 +70,7 @@ func Parse(supportedOptions map[string]bool, strict ...bool) (*Parser, error) {
|
||||
// the value item of `supportedOptions` indicates whether corresponding option name needs argument or not.
|
||||
//
|
||||
// The optional parameter `strict` specifies whether stops parsing and returns error if invalid option passed.
|
||||
func ParseArgs(args []string, supportedOptions map[string]bool, strict ...bool) (*Parser, error) {
|
||||
func ParseArgs(args []string, supportedOptions map[string]bool, option ...ParserOption) (*Parser, error) {
|
||||
if supportedOptions == nil {
|
||||
command.Init(args...)
|
||||
return &Parser{
|
||||
@ -72,12 +78,12 @@ func ParseArgs(args []string, supportedOptions map[string]bool, strict ...bool)
|
||||
parsedOptions: GetOptAll(),
|
||||
}, nil
|
||||
}
|
||||
strictParsing := false
|
||||
if len(strict) > 0 {
|
||||
strictParsing = strict[0]
|
||||
var parserOption ParserOption
|
||||
if len(option) > 0 {
|
||||
parserOption = option[0]
|
||||
}
|
||||
parser := &Parser{
|
||||
strict: strictParsing,
|
||||
option: parserOption,
|
||||
parsedArgs: make([]string, 0),
|
||||
parsedOptions: make(map[string]string),
|
||||
passedOptions: supportedOptions,
|
||||
@ -118,7 +124,7 @@ func ParseArgs(args []string, supportedOptions map[string]bool, strict ...bool)
|
||||
}
|
||||
i++
|
||||
continue
|
||||
} else if parser.strict {
|
||||
} else if parser.option.Strict {
|
||||
return nil, gerror.NewCodef(gcode.CodeInvalidParameter, `invalid option '%s'`, args[i])
|
||||
}
|
||||
}
|
||||
@ -159,8 +165,18 @@ func (p *Parser) parseOption(argument string) string {
|
||||
}
|
||||
|
||||
func (p *Parser) isOptionValid(name string) bool {
|
||||
_, ok := p.supportedOptions[name]
|
||||
return ok
|
||||
// Case-Sensitive.
|
||||
if p.option.CaseSensitive {
|
||||
_, ok := p.supportedOptions[name]
|
||||
return ok
|
||||
}
|
||||
// Case-InSensitive.
|
||||
for optionName, _ := range p.supportedOptions {
|
||||
if gstr.Equal(optionName, name) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (p *Parser) isOptionNeedArgument(name string) bool {
|
||||
|
||||
50
os/gcmd/gcmd_z_unit_feature_object3_test.go
Normal file
50
os/gcmd/gcmd_z_unit_feature_object3_test.go
Normal file
@ -0,0 +1,50 @@
|
||||
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://github.com/gogf/gf.
|
||||
|
||||
package gcmd_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gcmd"
|
||||
"github.com/gogf/gf/v2/os/gctx"
|
||||
"github.com/gogf/gf/v2/test/gtest"
|
||||
)
|
||||
|
||||
type TestParamsCase struct {
|
||||
g.Meta `name:"root" root:"root"`
|
||||
}
|
||||
|
||||
type TestParamsCaseRootInput struct {
|
||||
g.Meta `name:"root"`
|
||||
Name string
|
||||
}
|
||||
type TestParamsCaseRootOutput struct {
|
||||
Content string
|
||||
}
|
||||
|
||||
func (c *TestParamsCase) Root(ctx context.Context, in TestParamsCaseRootInput) (out *TestParamsCaseRootOutput, err error) {
|
||||
out = &TestParamsCaseRootOutput{
|
||||
Content: in.Name,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func Test_Command_ParamsCase(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
var ctx = gctx.New()
|
||||
cmd, err := gcmd.NewFromObject(TestParamsCase{})
|
||||
t.AssertNil(err)
|
||||
|
||||
os.Args = []string{"root", "-name=john"}
|
||||
value, err := cmd.RunWithValueError(ctx)
|
||||
t.AssertNil(err)
|
||||
t.Assert(value, `{"Content":"john"}`)
|
||||
})
|
||||
}
|
||||
@ -82,8 +82,8 @@ const (
|
||||
)
|
||||
|
||||
const (
|
||||
patternKeyForRequired = `required`
|
||||
patternKeyForIn = `in:`
|
||||
validationRuleKeyForRequired = `required`
|
||||
validationRuleKeyForIn = `in:`
|
||||
)
|
||||
|
||||
var (
|
||||
|
||||
@ -80,8 +80,9 @@ func (oai *OpenApiV3) newParameterRefWithStructMethod(field gstructs.Field, path
|
||||
}
|
||||
|
||||
// Required check.
|
||||
if parameter.Schema.Value != nil && parameter.Schema.Value.Pattern != "" {
|
||||
if gset.NewStrSetFrom(gstr.Split(parameter.Schema.Value.Pattern, "|")).Contains(patternKeyForRequired) {
|
||||
if parameter.Schema.Value != nil && parameter.Schema.Value.ValidationRules != "" {
|
||||
validationRuleArray := gstr.Split(parameter.Schema.Value.ValidationRules, "|")
|
||||
if gset.NewStrSetFrom(validationRuleArray).Contains(validationRuleKeyForRequired) {
|
||||
parameter.Required = true
|
||||
}
|
||||
}
|
||||
|
||||
@ -60,6 +60,7 @@ type Schema struct {
|
||||
AdditionalProperties *SchemaRef `json:"additionalProperties,omitempty"`
|
||||
Discriminator *Discriminator `json:"discriminator,omitempty"`
|
||||
XExtensions XExtensions `json:"-"`
|
||||
ValidationRules string `json:"-"`
|
||||
}
|
||||
|
||||
func (s Schema) MarshalJSON() ([]byte, error) {
|
||||
@ -183,9 +184,9 @@ func (oai *OpenApiV3) structToSchema(object interface{}) (*Schema, error) {
|
||||
}
|
||||
|
||||
schema.Properties.Iterator(func(key string, ref SchemaRef) bool {
|
||||
if ref.Value != nil && ref.Value.Pattern != "" {
|
||||
validationRuleSet := gset.NewStrSetFrom(gstr.Split(ref.Value.Pattern, "|"))
|
||||
if validationRuleSet.Contains(patternKeyForRequired) {
|
||||
if ref.Value != nil && ref.Value.ValidationRules != "" {
|
||||
validationRuleSet := gset.NewStrSetFrom(gstr.Split(ref.Value.ValidationRules, "|"))
|
||||
if validationRuleSet.Contains(validationRuleKeyForRequired) {
|
||||
schema.Required = append(schema.Required, key)
|
||||
}
|
||||
}
|
||||
@ -212,14 +213,14 @@ func (oai *OpenApiV3) tagMapToSchema(tagMap map[string]string, schema *Schema) e
|
||||
for _, tag := range gvalid.GetTags() {
|
||||
if validationTagValue, ok := tagMap[tag]; ok {
|
||||
_, validationRules, _ := gvalid.ParseTagValue(validationTagValue)
|
||||
schema.Pattern = validationRules
|
||||
schema.ValidationRules = validationRules
|
||||
// Enum checks.
|
||||
if len(schema.Enum) == 0 {
|
||||
for _, rule := range gstr.SplitAndTrim(validationRules, "|") {
|
||||
if gstr.HasPrefix(rule, patternKeyForIn) {
|
||||
if gstr.HasPrefix(rule, validationRuleKeyForIn) {
|
||||
var (
|
||||
isAllEnumNumber = true
|
||||
enumArray = gstr.SplitAndTrim(rule[len(patternKeyForIn):], ",")
|
||||
enumArray = gstr.SplitAndTrim(rule[len(validationRuleKeyForIn):], ",")
|
||||
)
|
||||
for _, enum := range enumArray {
|
||||
if !gstr.IsNumeric(enum) {
|
||||
|
||||
@ -11,7 +11,7 @@ import (
|
||||
)
|
||||
|
||||
// XExtensions stores the `x-` custom extensions.
|
||||
type XExtensions map[string]interface{}
|
||||
type XExtensions map[string]string
|
||||
|
||||
func (oai *OpenApiV3) tagMapToXExtensions(tagMap map[string]string, extensions XExtensions) {
|
||||
for k, v := range tagMap {
|
||||
|
||||
Reference in New Issue
Block a user