1
0
mirror of https://github.com/gogf/gf.git synced 2025-04-05 11:18:50 +08:00

fix(database/gdb): remove support of Array/Value/Count operations for result that has multiple record fields (#3839)

This commit is contained in:
John Guo 2024-10-08 20:42:06 +08:00 committed by GitHub
parent 7cbc9e8533
commit 91884e7c93
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
20 changed files with 239 additions and 65 deletions

View File

@ -23,7 +23,8 @@ type Driver struct {
}
const (
quoteChar = `"`
rowNumberAliasForSelect = `ROW_NUMBER__`
quoteChar = `"`
)
func init() {

View File

@ -0,0 +1,29 @@
// 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 mssql
import (
"context"
"github.com/gogf/gf/v2/database/gdb"
)
// DoCommit commits current sql and arguments to underlying sql driver.
func (d *Driver) DoCommit(ctx context.Context, in gdb.DoCommitInput) (out gdb.DoCommitOutput, err error) {
out, err = d.Core.DoCommit(ctx, in)
if err != nil {
return
}
if len(out.Records) > 0 {
// remove auto added field.
for i, record := range out.Records {
delete(record, rowNumberAliasForSelect)
out.Records[i] = record
}
}
return
}

View File

@ -21,8 +21,8 @@ var (
orderBySqlTmp = `SELECT %s %s OFFSET %d ROWS FETCH NEXT %d ROWS ONLY`
withoutOrderBySqlTmp = `SELECT %s OFFSET %d ROWS FETCH NEXT %d ROWS ONLY`
selectWithOrderSqlTmp = `
SELECT * FROM (SELECT ROW_NUMBER() OVER (ORDER BY %s) as ROWNUMBER_, %s ) as TMP_
WHERE TMP_.ROWNUMBER_ > %d AND TMP_.ROWNUMBER_ <= %d
SELECT * FROM (SELECT ROW_NUMBER() OVER (ORDER BY %s) as ROW_NUMBER__, %s ) as TMP_
WHERE TMP_.ROW_NUMBER__ > %d AND TMP_.ROW_NUMBER__ <= %d
`
)

View File

@ -13,6 +13,8 @@ import (
)
// DoFilter handles the sql before posts it to database.
func (d *Driver) DoFilter(ctx context.Context, link gdb.Link, sql string, args []interface{}) (newSql string, newArgs []interface{}, err error) {
func (d *Driver) DoFilter(
ctx context.Context, link gdb.Link, sql string, args []interface{},
) (newSql string, newArgs []interface{}, err error) {
return d.Core.DoFilter(ctx, link, sql, args)
}

View File

@ -1278,3 +1278,70 @@ func Test_Issue3754(t *testing.T) {
t.Assert(oneDeleteUnscoped["update_at"].String(), "")
})
}
// https://github.com/gogf/gf/issues/3626
func Test_Issue3626(t *testing.T) {
table := "issue3626"
array := gstr.SplitAndTrim(gtest.DataContent(`issue3626.sql`), ";")
for _, v := range array {
if _, err := db.Exec(ctx, v); err != nil {
gtest.Error(err)
}
}
defer dropTable(table)
// Insert.
gtest.C(t, func(t *gtest.T) {
dataInsert := g.Map{
"id": 1,
"name": "name_1",
}
r, err := db.Model(table).Data(dataInsert).Insert()
t.AssertNil(err)
n, _ := r.RowsAffected()
t.Assert(n, 1)
oneInsert, err := db.Model(table).WherePri(1).One()
t.AssertNil(err)
t.Assert(oneInsert["id"].Int(), 1)
t.Assert(oneInsert["name"].String(), "name_1")
})
var (
cacheKey = guid.S()
cacheFunc = func(duration time.Duration) gdb.HookHandler {
return gdb.HookHandler{
Select: func(ctx context.Context, in *gdb.HookSelectInput) (result gdb.Result, err error) {
get, err := db.GetCache().Get(ctx, cacheKey)
if err == nil && !get.IsEmpty() {
err = get.Scan(&result)
if err == nil {
return result, nil
}
}
result, err = in.Next(ctx)
if err != nil {
return nil, err
}
if result == nil || result.Len() < 1 {
result = make(gdb.Result, 0)
}
_ = db.GetCache().Set(ctx, cacheKey, result, duration)
return
},
}
}
)
gtest.C(t, func(t *gtest.T) {
defer db.GetCache().Clear(ctx)
count, err := db.Model(table).Count()
t.AssertNil(err)
t.Assert(count, 1)
count, err = db.Model(table).Hook(cacheFunc(time.Hour)).Count()
t.AssertNil(err)
t.Assert(count, 1)
count, err = db.Model(table).Hook(cacheFunc(time.Hour)).Count()
t.AssertNil(err)
t.Assert(count, 1)
})
}

View File

@ -761,7 +761,7 @@ func Test_Model_Value_WithCache(t *testing.T) {
value, err := db.Model(table).Where("id", 1).Cache(gdb.CacheOption{
Duration: time.Second * 10,
Force: false,
}).Value()
}).Value("id")
t.AssertNil(err)
t.Assert(value.Int(), 1)
})
@ -2965,13 +2965,13 @@ func Test_Model_FieldsEx_AutoMapping(t *testing.T) {
// "create_time": gtime.NewFromStr("2018-10-24 10:00:00").String(),
gtest.C(t, func(t *gtest.T) {
value, err := db.Model(table).FieldsEx("Passport, Password, NickName, CreateTime").Where("id", 2).Value()
value, err := db.Model(table).FieldsEx("create_date, Passport, Password, NickName, CreateTime").Where("id", 2).Value()
t.AssertNil(err)
t.Assert(value.Int(), 2)
})
gtest.C(t, func(t *gtest.T) {
value, err := db.Model(table).FieldsEx("ID, Passport, Password, CreateTime").Where("id", 2).Value()
value, err := db.Model(table).FieldsEx("create_date, ID, Passport, Password, CreateTime").Where("id", 2).Value()
t.AssertNil(err)
t.Assert(value.String(), "name_2")
})

View File

@ -0,0 +1,5 @@
CREATE TABLE `issue3626` (
id int(11) NOT NULL,
name varchar(45) DEFAULT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

View File

@ -21,7 +21,8 @@ type Driver struct {
}
const (
quoteChar = `"`
rowNumberAliasForSelect = `ROW_NUMBER__`
quoteChar = `"`
)
func init() {

View File

@ -0,0 +1,29 @@
// 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 oracle
import (
"context"
"github.com/gogf/gf/v2/database/gdb"
)
// DoCommit commits current sql and arguments to underlying sql driver.
func (d *Driver) DoCommit(ctx context.Context, in gdb.DoCommitInput) (out gdb.DoCommitOutput, err error) {
out, err = d.Core.DoCommit(ctx, in)
if err != nil {
return
}
if len(out.Records) > 0 {
// remove auto added field.
for i, record := range out.Records {
delete(record, rowNumberAliasForSelect)
out.Records[i] = record
}
}
return
}

View File

@ -20,9 +20,8 @@ import (
var (
newSqlReplacementTmp = `
SELECT * FROM (
SELECT GFORM.*, ROWNUM ROWNUM_ FROM (%s %s) GFORM WHERE ROWNUM <= %d
)
WHERE ROWNUM_ > %d
SELECT GFORM.*, ROWNUM ROW_NUMBER__ FROM (%s %s) GFORM WHERE ROWNUM <= %d
) WHERE ROW_NUMBER__ > %d
`
)

View File

@ -31,9 +31,13 @@ func (d *Driver) DoFilter(
// Refer:
// https://github.com/gogf/gf/issues/1537
// https://www.postgresql.org/docs/12/functions-json.html
newSql, err = gregex.ReplaceStringFuncMatch(`(::jsonb([^\w\d]*)\$\d)`, newSql, func(match []string) string {
return fmt.Sprintf(`::jsonb%s?`, match[2])
})
newSql, err = gregex.ReplaceStringFuncMatch(
`(::jsonb([^\w\d]*)\$\d)`,
newSql,
func(match []string) string {
return fmt.Sprintf(`::jsonb%s?`, match[2])
},
)
if err != nil {
return "", nil, err
}

View File

@ -14,7 +14,9 @@ import (
)
// DoFilter deals with the sql string before commits it to underlying sql driver.
func (d *Driver) DoFilter(ctx context.Context, link gdb.Link, sql string, args []interface{}) (newSql string, newArgs []interface{}, err error) {
func (d *Driver) DoFilter(
ctx context.Context, link gdb.Link, sql string, args []interface{},
) (newSql string, newArgs []interface{}, err error) {
// Special insert/ignore operation for sqlite.
switch {
case gstr.HasPrefix(sql, gdb.InsertOperationIgnore):

View File

@ -16,7 +16,9 @@ import (
)
// DoFilter deals with the sql string before commits it to underlying sql driver.
func (d *Driver) DoFilter(ctx context.Context, link gdb.Link, sql string, args []interface{}) (newSql string, newArgs []interface{}, err error) {
func (d *Driver) DoFilter(
ctx context.Context, link gdb.Link, sql string, args []interface{},
) (newSql string, newArgs []interface{}, err error) {
// Special insert/ignore operation for sqlite.
switch {
case gstr.HasPrefix(sql, gdb.InsertOperationIgnore):

View File

@ -635,6 +635,8 @@ func Instance(name ...string) (db DB, err error) {
// getConfigNodeByGroup calculates and returns a configuration node of given group. It
// calculates the value internally using weight algorithm for load balance.
//
// The returned node is a clone of configuration node, which is safe for later modification.
//
// The parameter `master` specifies whether retrieving a master node, or else a slave node
// if master-slave configured.
func getConfigNodeByGroup(group string, master bool) (*ConfigNode, error) {
@ -674,6 +676,7 @@ func getConfigNodeByGroup(group string, master bool) (*ConfigNode, error) {
}
// getConfigNodeByWeight calculates the configuration weights and randomly returns a node.
// The returned node is a clone of configuration node, which is safe for later modification.
//
// Calculation algorithm brief:
// 1. If we have 2 nodes, and their weights are both 1, then the weight range is [0, 199];
@ -729,6 +732,7 @@ func (c *Core) getSqlDb(master bool, schema ...string) (sqlDb *sql.DB, err error
configs.RLock()
defer configs.RUnlock()
// Value COPY for node.
// The returned node is a clone of configuration node, which is safe for later modification.
node, err = getConfigNodeByGroup(c.group, master)
if err != nil {
return nil, err
@ -777,7 +781,7 @@ func (c *Core) getSqlDb(master bool, schema ...string) (sqlDb *sql.DB, err error
}
return sqlDb
}
// it here uses node value not pointer as the cache key, in case of oracle ORA-12516 error.
// it here uses NODE VALUE not pointer as the cache key, in case of oracle ORA-12516 error.
instanceValue = c.links.GetOrSetFuncLock(*node, instanceCacheFunc)
)
if instanceValue != nil && sqlDb == nil {

View File

@ -697,7 +697,7 @@ func (c *Core) FilteredLink() string {
//
// Note that this interface implements mainly for workaround for a json infinite loop bug
// of Golang version < v1.14.
func (c Core) MarshalJSON() ([]byte, error) {
func (c *Core) MarshalJSON() ([]byte, error) {
return []byte(fmt.Sprintf(`%+v`, c)), nil
}

View File

@ -23,6 +23,8 @@ type internalCtxData struct {
}
// column stores column data in ctx for internal usage purpose.
// Deprecated.
// TODO remove this usage in future.
type internalColumnData struct {
// The first column in result response from database server.
// This attribute is used for Value/Count selection statement purpose,

View File

@ -53,7 +53,9 @@ func (c *Core) DoQuery(ctx context.Context, link Link, sql string, args ...inter
}
if c.db.GetConfig().QueryTimeout > 0 {
ctx, _ = context.WithTimeout(ctx, c.db.GetConfig().QueryTimeout)
var cancelFunc context.CancelFunc
ctx, cancelFunc = context.WithTimeout(ctx, c.db.GetConfig().QueryTimeout)
defer cancelFunc()
}
// Sql filtering.
@ -83,6 +85,9 @@ func (c *Core) DoQuery(ctx context.Context, link Link, sql string, args ...inter
Type: SqlTypeQueryContext,
IsTransaction: link.IsTransaction(),
})
if err != nil {
return nil, err
}
return out.Records, err
}
@ -144,13 +149,18 @@ func (c *Core) DoExec(ctx context.Context, link Link, sql string, args ...interf
Type: SqlTypeExecContext,
IsTransaction: link.IsTransaction(),
})
if err != nil {
return nil, err
}
return out.Result, err
}
// DoFilter is a hook function, which filters the sql and its arguments before it's committed to underlying driver.
// The parameter `link` specifies the current database connection operation object. You can modify the sql
// string `sql` and its arguments `args` as you wish before they're committed to driver.
func (c *Core) DoFilter(ctx context.Context, link Link, sql string, args []interface{}) (newSql string, newArgs []interface{}, err error) {
func (c *Core) DoFilter(
ctx context.Context, link Link, sql string, args []interface{},
) (newSql string, newArgs []interface{}, err error) {
return sql, args, nil
}
@ -322,7 +332,6 @@ func (c *Core) DoPrepare(ctx context.Context, link Link, sql string) (stmt *Stmt
link = &txLink{tx.GetSqlTX()}
} else {
// Or else it creates one from master node.
var err error
if link, err = c.MasterLink(); err != nil {
return nil, err
}
@ -336,7 +345,9 @@ func (c *Core) DoPrepare(ctx context.Context, link Link, sql string) (stmt *Stmt
if c.db.GetConfig().PrepareTimeout > 0 {
// DO NOT USE cancel function in prepare statement.
ctx, _ = context.WithTimeout(ctx, c.db.GetConfig().PrepareTimeout)
var cancelFunc context.CancelFunc
ctx, cancelFunc = context.WithTimeout(ctx, c.db.GetConfig().PrepareTimeout)
defer cancelFunc()
}
// Link execution.
@ -347,6 +358,9 @@ func (c *Core) DoPrepare(ctx context.Context, link Link, sql string) (stmt *Stmt
Type: SqlTypePrepareContext,
IsTransaction: link.IsTransaction(),
})
if err != nil {
return nil, err
}
return out.Stmt, err
}
@ -379,7 +393,7 @@ func (c *Core) FormatUpsert(columns []string, list List, option DoInsertOption)
}
} else {
for _, column := range columns {
// If it's SAVE operation, do not automatically update the creating time.
// If it's `SAVE` operation, do not automatically update the creating time.
if c.IsSoftCreatedFieldName(column) {
continue
}
@ -474,6 +488,7 @@ func (c *Core) columnValueToLocalValue(ctx context.Context, value interface{}, c
gconv.String(value),
columnType.ScanType().String(),
), nil
default:
}
}
// Other complex types, especially custom types.

View File

@ -12,6 +12,7 @@ import (
"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/reflection"
@ -139,20 +140,21 @@ func (m *Model) Array(fieldsAndWhere ...interface{}) ([]Value, error) {
if err != nil {
return nil, err
}
var (
field string
core = m.db.GetCore()
ctx = core.injectInternalColumn(m.GetCtx())
)
var field string
if len(all) > 0 {
if internalData := core.getInternalColumnFromCtx(ctx); internalData != nil {
field = internalData.FirstResultColumn
} else {
return nil, gerror.NewCode(
gcode.CodeInternalError,
`query array error: the internal context data is missing. there's internal issue should be fixed`,
var recordFields = m.getRecordFields(all[0])
if len(recordFields) > 1 {
// it returns error if there are multiple fields in the result record.
return nil, gerror.NewCodef(
gcode.CodeInvalidParameter,
`invalid fields for "Array" operation, result fields number "%d"%s, but expect one`,
len(recordFields),
gjson.MustEncodeString(recordFields),
)
}
if len(recordFields) == 1 {
field = recordFields[0]
}
}
return all.Array(field), nil
}
@ -401,20 +403,34 @@ func (m *Model) Value(fieldsAndWhere ...interface{}) (Value, error) {
return nil, err
}
if len(all) > 0 {
if internalData := core.getInternalColumnFromCtx(ctx); internalData != nil {
if v, ok := all[0][internalData.FirstResultColumn]; ok {
var recordFields = m.getRecordFields(all[0])
if len(recordFields) == 1 {
for _, v := range all[0] {
return v, nil
}
} else {
return nil, gerror.NewCode(
gcode.CodeInternalError,
`query value error: the internal context data is missing. there's internal issue should be fixed`,
)
}
// it returns error if there are multiple fields in the result record.
return nil, gerror.NewCodef(
gcode.CodeInvalidParameter,
`invalid fields for "Value" operation, result fields number "%d"%s, but expect one`,
len(recordFields),
gjson.MustEncodeString(recordFields),
)
}
return nil, nil
}
func (m *Model) getRecordFields(record Record) []string {
if len(record) == 0 {
return nil
}
var fields = make([]string, 0)
for k := range record {
fields = append(fields, k)
}
return fields
}
// Count does "SELECT COUNT(x) FROM ..." statement for the model.
// The optional parameter `where` is the same as the parameter of Model.Where function,
// see Model.Where.
@ -434,16 +450,19 @@ func (m *Model) Count(where ...interface{}) (int, error) {
return 0, err
}
if len(all) > 0 {
if internalData := core.getInternalColumnFromCtx(ctx); internalData != nil {
if v, ok := all[0][internalData.FirstResultColumn]; ok {
var recordFields = m.getRecordFields(all[0])
if len(recordFields) == 1 {
for _, v := range all[0] {
return v.Int(), nil
}
} else {
return 0, gerror.NewCode(
gcode.CodeInternalError,
`query count error: the internal context data is missing. there's internal issue should be fixed`,
)
}
// it returns error if there are multiple fields in the result record.
return 0, gerror.NewCodef(
gcode.CodeInvalidParameter,
`invalid fields for "Count" operation, result fields number "%d"%s, but expect one`,
len(recordFields),
gjson.MustEncodeString(recordFields),
)
}
return 0, nil
}

View File

@ -274,8 +274,8 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
github.com/dlclark/regexp2 v1.7.0 h1:7lJfhqlPssTb1WQx4yvTHN0uElPEv52sbaECrAQxjAo=
github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
github.com/dlclark/regexp2 v1.11.2 h1:/u628IuisSTwri5/UKloiIsH8+qF2Pu7xEQX+yIKg68=
github.com/dlclark/regexp2 v1.11.2/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
github.com/emicklei/go-restful/v3 v3.9.0 h1:XwGDlfxEnQZzuopoqxwSEllNcCOM9DhhFyhFIIGKwxE=
@ -622,11 +622,10 @@ github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZ
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/polarismesh/polaris-go v1.5.5 h1:TUxgla21J9Zb3zSynoAA9og0+sYJZ7TpZ2aFwzH7woI=
github.com/polarismesh/polaris-go v1.5.5/go.mod h1:CuXO9bhHGjSoOIMWr4NXf3bJAkRBp5YoM7ibBzENC+c=
github.com/polarismesh/polaris-go v1.5.8 h1:zBZkZBa4wVxsG5Y/6U4PmY9dY/mddXdfNI65edVu6U8=
github.com/polarismesh/polaris-go v1.5.8/go.mod h1:CuXO9bhHGjSoOIMWr4NXf3bJAkRBp5YoM7ibBzENC+c=
github.com/polarismesh/specification v1.4.1 h1:lTZqeyUhhWuKyr6NDKBwmUrNfcUDvKLxWT/uOq71T5A=
github.com/polarismesh/specification v1.4.1/go.mod h1:rDvMMtl5qebPmqiBLNa5Ps0XtwkP31ZLirbH4kXA0YU=
github.com/polarismesh/specification v1.5.1 h1:cJ2m0RBepdopGo/e3UpKdsab3NpDZnw5IsVTB1sFc5I=
github.com/polarismesh/specification v1.5.1/go.mod h1:rDvMMtl5qebPmqiBLNa5Ps0XtwkP31ZLirbH4kXA0YU=
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s=
@ -799,8 +798,7 @@ golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I=
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30=
golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M=
golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw=
golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54=
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@ -904,8 +902,7 @@ golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ=
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys=
golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE=
golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE=
golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@ -947,8 +944,7 @@ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@ -1040,8 +1036,7 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg=
golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
@ -1050,8 +1045,7 @@ golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.9.0/go.mod h1:M6DEAAIenWoTxdKrOltXcmDY3rSplQUkrvaDU5FcQyo=
golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
golang.org/x/term v0.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk=
golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4=
golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU=
golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@ -1067,8 +1061,7 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc=
golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=

View File

@ -256,7 +256,7 @@ func (p *Parser) GetArgAll() []string {
}
// MarshalJSON implements the interface MarshalJSON for json.Marshal.
func (p Parser) MarshalJSON() ([]byte, error) {
func (p *Parser) MarshalJSON() ([]byte, error) {
return json.Marshal(map[string]interface{}{
"parsedArgs": p.parsedArgs,
"parsedOptions": p.parsedOptions,