mirror of
https://gitee.com/johng/gf
synced 2026-06-05 18:15:43 +08:00
fix(database/gdb): Fix GetArray return type and add Bools method (#4452)
Change the return type of the GetArray method to Array for consistency
in data structure. Introduce a new Bools method to convert Vars to a
slice of bools, along with corresponding test cases to validate the
functionality.
```go
// 改进前
res, _ := db.Model(table).Fields("id").Array()
ids := make([]int64, 0, len(res))
for _, v := range res {
ids = append(ids, v.Int64())
}
g.Dump(ids)
// 改进后
res, _ := db.Model(table).Fields("id").Array()
ids := res.Int64s()
g.Dump(ids)
```
This commit is contained in:
@ -15,14 +15,25 @@ type Vars []*Var
|
||||
|
||||
// Strings converts and returns `vs` as []string.
|
||||
func (vs Vars) Strings() (s []string) {
|
||||
s = make([]string, 0, len(vs))
|
||||
for _, v := range vs {
|
||||
s = append(s, v.String())
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// Bools converts and returns `vs` as []bool.
|
||||
func (vs Vars) Bools() (s []bool) {
|
||||
s = make([]bool, 0, len(vs))
|
||||
for _, v := range vs {
|
||||
s = append(s, v.Bool())
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// Interfaces converts and returns `vs` as []any.
|
||||
func (vs Vars) Interfaces() (s []any) {
|
||||
s = make([]any, 0, len(vs))
|
||||
for _, v := range vs {
|
||||
s = append(s, v.Val())
|
||||
}
|
||||
@ -31,6 +42,7 @@ func (vs Vars) Interfaces() (s []any) {
|
||||
|
||||
// Float32s converts and returns `vs` as []float32.
|
||||
func (vs Vars) Float32s() (s []float32) {
|
||||
s = make([]float32, 0, len(vs))
|
||||
for _, v := range vs {
|
||||
s = append(s, v.Float32())
|
||||
}
|
||||
@ -39,6 +51,7 @@ func (vs Vars) Float32s() (s []float32) {
|
||||
|
||||
// Float64s converts and returns `vs` as []float64.
|
||||
func (vs Vars) Float64s() (s []float64) {
|
||||
s = make([]float64, 0, len(vs))
|
||||
for _, v := range vs {
|
||||
s = append(s, v.Float64())
|
||||
}
|
||||
@ -47,6 +60,7 @@ func (vs Vars) Float64s() (s []float64) {
|
||||
|
||||
// Ints converts and returns `vs` as []Int.
|
||||
func (vs Vars) Ints() (s []int) {
|
||||
s = make([]int, 0, len(vs))
|
||||
for _, v := range vs {
|
||||
s = append(s, v.Int())
|
||||
}
|
||||
@ -55,6 +69,7 @@ func (vs Vars) Ints() (s []int) {
|
||||
|
||||
// Int8s converts and returns `vs` as []int8.
|
||||
func (vs Vars) Int8s() (s []int8) {
|
||||
s = make([]int8, 0, len(vs))
|
||||
for _, v := range vs {
|
||||
s = append(s, v.Int8())
|
||||
}
|
||||
@ -63,6 +78,7 @@ func (vs Vars) Int8s() (s []int8) {
|
||||
|
||||
// Int16s converts and returns `vs` as []int16.
|
||||
func (vs Vars) Int16s() (s []int16) {
|
||||
s = make([]int16, 0, len(vs))
|
||||
for _, v := range vs {
|
||||
s = append(s, v.Int16())
|
||||
}
|
||||
@ -71,6 +87,7 @@ func (vs Vars) Int16s() (s []int16) {
|
||||
|
||||
// Int32s converts and returns `vs` as []int32.
|
||||
func (vs Vars) Int32s() (s []int32) {
|
||||
s = make([]int32, 0, len(vs))
|
||||
for _, v := range vs {
|
||||
s = append(s, v.Int32())
|
||||
}
|
||||
@ -79,6 +96,7 @@ func (vs Vars) Int32s() (s []int32) {
|
||||
|
||||
// Int64s converts and returns `vs` as []int64.
|
||||
func (vs Vars) Int64s() (s []int64) {
|
||||
s = make([]int64, 0, len(vs))
|
||||
for _, v := range vs {
|
||||
s = append(s, v.Int64())
|
||||
}
|
||||
@ -87,6 +105,7 @@ func (vs Vars) Int64s() (s []int64) {
|
||||
|
||||
// Uints converts and returns `vs` as []uint.
|
||||
func (vs Vars) Uints() (s []uint) {
|
||||
s = make([]uint, 0, len(vs))
|
||||
for _, v := range vs {
|
||||
s = append(s, v.Uint())
|
||||
}
|
||||
@ -95,6 +114,7 @@ func (vs Vars) Uints() (s []uint) {
|
||||
|
||||
// Uint8s converts and returns `vs` as []uint8.
|
||||
func (vs Vars) Uint8s() (s []uint8) {
|
||||
s = make([]uint8, 0, len(vs))
|
||||
for _, v := range vs {
|
||||
s = append(s, v.Uint8())
|
||||
}
|
||||
@ -103,6 +123,7 @@ func (vs Vars) Uint8s() (s []uint8) {
|
||||
|
||||
// Uint16s converts and returns `vs` as []uint16.
|
||||
func (vs Vars) Uint16s() (s []uint16) {
|
||||
s = make([]uint16, 0, len(vs))
|
||||
for _, v := range vs {
|
||||
s = append(s, v.Uint16())
|
||||
}
|
||||
@ -111,6 +132,7 @@ func (vs Vars) Uint16s() (s []uint16) {
|
||||
|
||||
// Uint32s converts and returns `vs` as []uint32.
|
||||
func (vs Vars) Uint32s() (s []uint32) {
|
||||
s = make([]uint32, 0, len(vs))
|
||||
for _, v := range vs {
|
||||
s = append(s, v.Uint32())
|
||||
}
|
||||
@ -119,6 +141,7 @@ func (vs Vars) Uint32s() (s []uint32) {
|
||||
|
||||
// Uint64s converts and returns `vs` as []uint64.
|
||||
func (vs Vars) Uint64s() (s []uint64) {
|
||||
s = make([]uint64, 0, len(vs))
|
||||
for _, v := range vs {
|
||||
s = append(s, v.Uint64())
|
||||
}
|
||||
|
||||
@ -22,6 +22,7 @@ func TestVars(t *testing.T) {
|
||||
gvar.New(3),
|
||||
}
|
||||
t.AssertEQ(vs.Strings(), []string{"1", "2", "3"})
|
||||
t.AssertEQ(vs.Bools(), []bool{true, true, true})
|
||||
t.AssertEQ(vs.Interfaces(), []any{1, 2, 3})
|
||||
t.AssertEQ(vs.Float32s(), []float32{1, 2, 3})
|
||||
t.AssertEQ(vs.Float64s(), []float64{1, 2, 3})
|
||||
@ -38,6 +39,46 @@ func TestVars(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestVars_Bools(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
// Test with various boolean-like values
|
||||
var vs = gvar.Vars{
|
||||
gvar.New(true),
|
||||
gvar.New(false),
|
||||
gvar.New(1),
|
||||
gvar.New(0),
|
||||
gvar.New("true"),
|
||||
gvar.New("false"),
|
||||
gvar.New("1"),
|
||||
gvar.New("0"),
|
||||
}
|
||||
expected := []bool{true, false, true, false, true, false, true, false}
|
||||
t.AssertEQ(vs.Bools(), expected)
|
||||
})
|
||||
}
|
||||
|
||||
func TestVars_Empty(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
// Test with empty Vars
|
||||
var vs = gvar.Vars{}
|
||||
t.AssertEQ(vs.Strings(), []string{})
|
||||
t.AssertEQ(vs.Bools(), []bool{})
|
||||
t.AssertEQ(vs.Interfaces(), []any{})
|
||||
t.AssertEQ(vs.Ints(), []int{})
|
||||
t.AssertEQ(vs.Float64s(), []float64{})
|
||||
})
|
||||
}
|
||||
|
||||
func TestVars_SingleElement(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
// Test with single element
|
||||
var vs = gvar.Vars{gvar.New(42)}
|
||||
t.AssertEQ(vs.Strings(), []string{"42"})
|
||||
t.AssertEQ(vs.Bools(), []bool{true})
|
||||
t.AssertEQ(vs.Ints(), []int{42})
|
||||
})
|
||||
}
|
||||
|
||||
func TestVars_Scan(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
type User struct {
|
||||
|
||||
@ -181,7 +181,7 @@ type DB interface {
|
||||
|
||||
// GetArray executes a query and returns the first column of all rows.
|
||||
// It's useful for queries like SELECT id FROM table.
|
||||
GetArray(ctx context.Context, sql string, args ...any) ([]Value, error)
|
||||
GetArray(ctx context.Context, sql string, args ...any) (Array, error)
|
||||
|
||||
// GetCount executes a COUNT query and returns the result as an integer.
|
||||
// It's a convenience method for counting rows.
|
||||
@ -673,6 +673,9 @@ type (
|
||||
// Value is the field value type.
|
||||
Value = *gvar.Var
|
||||
|
||||
// Array is the field value array type.
|
||||
Array = gvar.Vars
|
||||
|
||||
// Record is the row record of the table.
|
||||
Record map[string]Value
|
||||
|
||||
|
||||
@ -175,7 +175,7 @@ func (c *Core) GetOne(ctx context.Context, sql string, args ...any) (Record, err
|
||||
|
||||
// GetArray queries and returns data values as slice from database.
|
||||
// Note that if there are multiple columns in the result, it returns just one column values randomly.
|
||||
func (c *Core) GetArray(ctx context.Context, sql string, args ...any) ([]Value, error) {
|
||||
func (c *Core) GetArray(ctx context.Context, sql string, args ...any) (Array, error) {
|
||||
all, err := c.db.DoSelect(ctx, nil, sql, args...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@ -126,7 +126,7 @@ func (m *Model) One(where ...any) (Record, error) {
|
||||
// If the optional parameter `fieldsAndWhere` is given, the fieldsAndWhere[0] is the selected fields
|
||||
// and fieldsAndWhere[1:] is treated as where condition fields.
|
||||
// Also see Model.Fields and Model.Where functions.
|
||||
func (m *Model) Array(fieldsAndWhere ...any) ([]Value, error) {
|
||||
func (m *Model) Array(fieldsAndWhere ...any) (Array, error) {
|
||||
if len(fieldsAndWhere) > 0 {
|
||||
if len(fieldsAndWhere) > 2 {
|
||||
return m.Fields(gconv.String(fieldsAndWhere[0])).Where(fieldsAndWhere[1], fieldsAndWhere[2:]...).Array()
|
||||
|
||||
@ -76,8 +76,8 @@ func (r Result) List() List {
|
||||
// Array retrieves and returns specified column values as slice.
|
||||
// The parameter `field` is optional is the column field is only one.
|
||||
// The default `field` is the first field name of the first item in `Result` if parameter `field` is not given.
|
||||
func (r Result) Array(field ...string) []Value {
|
||||
array := make([]Value, len(r))
|
||||
func (r Result) Array(field ...string) Array {
|
||||
array := make(Array, len(r))
|
||||
if len(r) == 0 {
|
||||
return array
|
||||
}
|
||||
|
||||
@ -89,7 +89,7 @@ func Database(name ...string) gdb.DB {
|
||||
}
|
||||
}
|
||||
if len(cg) > 0 {
|
||||
if gdb.GetConfig(group) == nil {
|
||||
if gcg, _ := gdb.GetConfigGroup(group); gcg == nil {
|
||||
intlog.Printf(ctx, "add configuration for group: %s, %#v", g, cg)
|
||||
if err := gdb.SetConfigGroup(g, cg); err != nil {
|
||||
panic(err)
|
||||
@ -108,7 +108,7 @@ func Database(name ...string) gdb.DB {
|
||||
cg = append(cg, *node)
|
||||
}
|
||||
if len(cg) > 0 {
|
||||
if gdb.GetConfig(group) == nil {
|
||||
if gcg, _ := gdb.GetConfigGroup(group); gcg == nil {
|
||||
intlog.Printf(ctx, "add configuration for group: %s, %#v", gdb.DefaultGroupName, cg)
|
||||
if err := gdb.SetConfigGroup(gdb.DefaultGroupName, cg); err != nil {
|
||||
panic(err)
|
||||
|
||||
Reference in New Issue
Block a user