优化查询 去掉anymap 转为 stringmap

This commit is contained in:
xing 2023-02-21 18:25:52 +08:00
parent a319e7595f
commit 73fb725960
5 changed files with 274 additions and 125 deletions

View File

@ -17,18 +17,15 @@ func InitOptions() error {
if ctx == nil {
ctx = context.Background()
}
ops, err := model.SimpleFind[models.Options](ctx, model.SqlBuilder{{"autoload", "yes"}}, "option_name, option_value")
ops, err := model.FindToStringMap[models.Options](ctx, model.Conditions(
model.Where(model.SqlBuilder{{"autoload", "yes"}}),
model.Fields("option_name, option_value"),
))
if err != nil {
return err
}
if len(ops) == 0 {
ops, err = model.SimpleFind[models.Options](ctx, nil, "option_name, option_value")
if err != nil {
return err
}
}
for _, option := range ops {
options.Store(option.OptionName, option.OptionValue)
options.Store(option["option_name"], option["option_value"])
}
return nil
}
@ -38,7 +35,7 @@ func GetOption(k string) string {
if ok {
return v
}
vv, err := model.GetField[models.Options, string](ctx, "option_value", model.Conditions(model.Where(model.SqlBuilder{{"option_name", k}})))
vv, err := model.GetField[models.Options](ctx, "option_value", model.Conditions(model.Where(model.SqlBuilder{{"option_name", k}})))
options.Store(k, vv)
if err != nil {
return ""

View File

@ -100,12 +100,15 @@ func (p post) Table() string {
var ctx = context.Background()
var glob *SqlxQuery
func init() {
db, err := sqlx.Open("mysql", "root:root@tcp(192.168.66.47:3306)/wordpress?charset=utf8mb4&parseTime=True&loc=Local")
if err != nil {
panic(err)
}
InitDB(NewSqlxQuery(db, NewUniversalDb(nil, nil)))
glob = NewSqlxQuery(db, NewUniversalDb(nil, nil))
InitDB(glob)
}
func TestFind(t *testing.T) {
type args struct {

View File

@ -5,7 +5,6 @@ import (
"database/sql"
"errors"
"fmt"
"github.com/fthvgb1/wp-go/helper/maps"
"github.com/fthvgb1/wp-go/helper/slice"
"strings"
)
@ -156,51 +155,65 @@ func column[V Model, T any](db dbQuery, ctx context.Context, fn func(V) (T, bool
return
}
func GetField[T Model, V any](ctx context.Context, field string, q *QueryCondition) (r V, err error) {
r, err = getField[T, V](globalBb, ctx, field, q)
func GetField[T Model](ctx context.Context, field string, q *QueryCondition) (r string, err error) {
r, err = getField[T](globalBb, ctx, field, q)
return
}
func getField[T Model, V any](db dbQuery, ctx context.Context, field string, q *QueryCondition) (r V, err error) {
res, err := getToAnyMap[T](globalBb, ctx, q)
func getField[T Model](db dbQuery, ctx context.Context, field string, q *QueryCondition) (r string, err error) {
if q.fields == "" || q.fields == "*" {
q.fields = field
}
res, err := getToStringMap[T](db, ctx, q)
if err != nil {
return
}
r, ok := maps.GetStrAnyVal[V](res, field)
f := strings.Split(field, " ")
r, ok := res[f[len(f)-1]]
if !ok {
err = errors.New("not exists")
}
return
}
func GetFieldFromDB[T Model, V any](db dbQuery, ctx context.Context, field string, q *QueryCondition) (r V, err error) {
return getField[T, V](db, ctx, field, q)
func GetFieldFromDB[T Model](db dbQuery, ctx context.Context, field string, q *QueryCondition) (r string, err error) {
return getField[T](db, ctx, field, q)
}
func findToAnyMap[T Model](db dbQuery, ctx context.Context, q *QueryCondition) (r []map[string]any, err error) {
func getToStringMap[T Model](db dbQuery, ctx context.Context, q *QueryCondition) (r map[string]string, err error) {
rawSql, in, err := FindRawSql[T](q)
if err != nil {
return nil, err
}
ctx = context.WithValue(ctx, "toMap", true)
ctx = context.WithValue(ctx, "toMap", "string")
err = db.Get(ctx, &r, rawSql, in...)
return
}
func GetToStringMap[T Model](ctx context.Context, q *QueryCondition) (r map[string]string, err error) {
r, err = getToStringMap[T](globalBb, ctx, q)
return
}
func findToStringMap[T Model](db dbQuery, ctx context.Context, q *QueryCondition) (r []map[string]string, err error) {
rawSql, in, err := FindRawSql[T](q)
if err != nil {
return nil, err
}
ctx = context.WithValue(ctx, "toMap", "string")
err = db.Select(ctx, &r, rawSql, in...)
return
}
func FindToAnyMap[T Model](ctx context.Context, q *QueryCondition) (r []map[string]any, err error) {
r, err = findToAnyMap[T](globalBb, ctx, q)
func FindToStringMap[T Model](ctx context.Context, q *QueryCondition) (r []map[string]string, err error) {
r, err = findToStringMap[T](globalBb, ctx, q)
return
}
func FindToAnyMapFromDB[T Model](db dbQuery, ctx context.Context, q *QueryCondition) (r []map[string]any, err error) {
r, err = findToAnyMap[T](db, ctx, q)
func FindToStringMapFromDB[T Model](db dbQuery, ctx context.Context, q *QueryCondition) (r []map[string]string, err error) {
r, err = findToStringMap[T](db, ctx, q)
return
}
func getToAnyMap[T Model](db dbQuery, ctx context.Context, q *QueryCondition) (r map[string]any, err error) {
rawSql, in, err := FindRawSql[T](q)
if err != nil {
return nil, err
}
ctx = context.WithValue(ctx, "toMap", true)
err = db.Get(ctx, &r, rawSql, in...)
func GetToStringMapFromDB[T Model](db dbQuery, ctx context.Context, q *QueryCondition) (r map[string]string, err error) {
r, err = getToStringMap[T](db, ctx, q)
return
}

View File

@ -274,44 +274,6 @@ func TestColumn(t *testing.T) {
}
}
func TestGetField(t *testing.T) {
type args struct {
ctx context.Context
field string
q *QueryCondition
}
type testCase[V any] struct {
name string
args args
wantR V
wantErr bool
}
tests := []testCase[string]{
{
name: "t1",
args: args{
ctx: ctx,
field: "option_value",
q: Conditions(Where(SqlBuilder{{"option_name", "blogname"}})),
},
wantR: "记录并见证自己的成长",
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
gotR, err := GetField[options, string](tt.args.ctx, tt.args.field, tt.args.q)
if (err != nil) != tt.wantErr {
t.Errorf("GetField() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(gotR, tt.wantR) {
t.Errorf("GetField() gotR = %v, want %v", gotR, tt.wantR)
}
})
}
}
type options struct {
OptionId uint64 `gorm:"column:option_id" db:"option_id" json:"option_id" form:"option_id"`
OptionName string `gorm:"column:option_name" db:"option_name" json:"option_name" form:"option_name"`
@ -326,3 +288,190 @@ func (w options) PrimaryKey() string {
func (w options) Table() string {
return "wp_options"
}
func Test_getField(t *testing.T) {
{
name := "string"
db := glob
field := "option_value"
q := Conditions(Where(SqlBuilder{{"option_name", "blogname"}}))
wantR := "记录并见证自己的成长"
wantErr := false
t.Run(name, func(t *testing.T) {
gotR, err := getField[options](db, ctx, field, q)
if (err != nil) != wantErr {
t.Errorf("getField() error = %v, wantErr %v", err, wantErr)
return
}
if !reflect.DeepEqual(gotR, wantR) {
t.Errorf("getField() gotR = %v, want %v", gotR, wantR)
}
})
}
{
name := "t2"
db := glob
field := "option_id"
q := Conditions(Where(SqlBuilder{{"option_name", "blogname"}}))
wantR := "3"
wantErr := false
t.Run(name, func(t *testing.T) {
gotR, err := getField[options](db, ctx, field, q)
if (err != nil) != wantErr {
t.Errorf("getField() error = %v, wantErr %v", err, wantErr)
return
}
if !reflect.DeepEqual(gotR, wantR) {
t.Errorf("getField() gotR = %v, want %v", gotR, wantR)
}
})
}
{
name := "count(*)"
db := glob
field := "count(*)"
q := Conditions()
wantR := "386"
wantErr := false
t.Run(name, func(t *testing.T) {
gotR, err := getField[options](db, ctx, field, q)
if (err != nil) != wantErr {
t.Errorf("getField() error = %v, wantErr %v", err, wantErr)
return
}
if !reflect.DeepEqual(gotR, wantR) {
t.Errorf("getField() gotR = %v, want %v", gotR, wantR)
}
})
}
}
func Test_getToStringMap(t *testing.T) {
type args struct {
db dbQuery
ctx context.Context
q *QueryCondition
}
tests := []struct {
name string
args args
wantR map[string]string
wantErr bool
}{
{
name: "t1",
args: args{
db: glob,
ctx: ctx,
q: Conditions(Where(SqlBuilder{{"option_name", "users_can_register"}})),
},
wantR: map[string]string{
"option_id": "5",
"option_value": "0",
"option_name": "users_can_register",
"autoload": "yes",
},
},
{
name: "t2",
args: args{
db: glob,
ctx: ctx,
q: Conditions(
Where(SqlBuilder{{"option_name", "users_can_register"}}),
Fields("option_id id"),
),
},
wantR: map[string]string{
"id": "5",
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
gotR, err := getToStringMap[options](tt.args.db, tt.args.ctx, tt.args.q)
if (err != nil) != tt.wantErr {
t.Errorf("getToStringMap() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(gotR, tt.wantR) {
t.Errorf("getToStringMap() gotR = %v, want %v", gotR, tt.wantR)
}
})
}
}
func Test_findToStringMap(t *testing.T) {
type args struct {
db dbQuery
ctx context.Context
q *QueryCondition
}
tests := []struct {
name string
args args
wantR []map[string]string
wantErr bool
}{
{
name: "t1",
args: args{
db: glob,
ctx: ctx,
q: Conditions(Where(SqlBuilder{{"option_id", "5"}})),
},
wantR: []map[string]string{{
"option_id": "5",
"option_value": "0",
"option_name": "users_can_register",
"autoload": "yes",
}},
wantErr: false,
},
{
name: "t2",
args: args{
db: glob,
ctx: ctx,
q: Conditions(
Where(SqlBuilder{{"option_id", "5"}}),
Fields("option_value,option_name"),
),
},
wantR: []map[string]string{{
"option_value": "0",
"option_name": "users_can_register",
}},
wantErr: false,
},
{
name: "t3",
args: args{
db: glob,
ctx: ctx,
q: Conditions(
Where(SqlBuilder{{"option_id", "5"}}),
Fields("option_value v,option_name k"),
),
},
wantR: []map[string]string{{
"v": "0",
"k": "users_can_register",
}},
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
gotR, err := findToStringMap[options](tt.args.db, tt.args.ctx, tt.args.q)
if (err != nil) != tt.wantErr {
t.Errorf("findToStringMap() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(gotR, tt.wantR) {
t.Errorf("findToStringMap() gotR = %v, want %v", gotR, tt.wantR)
}
})
}
}

View File

@ -3,6 +3,7 @@ package model
import (
"context"
"fmt"
"github.com/fthvgb1/wp-go/helper/slice"
"github.com/jmoiron/sqlx"
"strconv"
"strings"
@ -35,11 +36,11 @@ func SetGet(db *SqlxQuery, fn func(context.Context, any, string, ...any) error)
func (r *SqlxQuery) Selects(ctx context.Context, dest any, sql string, params ...any) error {
v := ctx.Value("toMap")
if v != nil {
vv, ok := v.(bool)
if ok && vv {
d, ok := dest.(*[]map[string]any)
if ok {
return r.toMapSlice(d, sql, params...)
vv, ok := v.(string)
if ok && vv != "" {
switch vv {
case "string":
return ToMapSlice(r.sqlx, dest.(*[]map[string]string), sql, params...)
}
}
}
@ -49,77 +50,39 @@ func (r *SqlxQuery) Selects(ctx context.Context, dest any, sql string, params ..
func (r *SqlxQuery) Gets(ctx context.Context, dest any, sql string, params ...any) error {
v := ctx.Value("toMap")
if v != nil {
vv, ok := v.(bool)
if ok && vv {
d, ok := dest.(*map[string]any)
if ok {
return r.toMap(d, sql, params...)
vv, ok := v.(string)
if ok && vv != "" {
switch vv {
case "string":
return GetToMap(r.sqlx, dest.(*map[string]string), sql, params...)
}
}
}
return r.sqlx.Get(dest, sql, params...)
}
func (r *SqlxQuery) toMap(dest *map[string]any, sql string, params ...any) (err error) {
rows := r.sqlx.QueryRowx(sql, params...)
columns, err := rows.Columns()
if err != nil {
return err
}
columnLen := len(columns)
c := make([]any, columnLen)
for i, _ := range c {
var a any
c[i] = &a
}
err = rows.Scan(c...)
if err != nil {
return
}
v := make(map[string]any)
for i, data := range c {
s, ok := data.(*any)
if ok {
ss, ok := (*s).([]uint8)
if ok {
data = string(ss)
}
}
v[columns[i]] = data
}
*dest = v
return
}
func (r *SqlxQuery) toMapSlice(dest *[]map[string]any, sql string, params ...any) (err error) {
rows, err := r.sqlx.Query(sql, params...)
func ToMapSlice[V any](db *sqlx.DB, dest *[]map[string]V, sql string, params ...any) (err error) {
rows, err := db.Query(sql, params...)
columns, err := rows.Columns()
if err != nil {
return err
}
defer rows.Close()
columnLen := len(columns)
c := make([]any, columnLen)
c := make([]*V, columnLen)
for i, _ := range c {
var a any
var a V
c[i] = &a
}
var m []map[string]any
var m []map[string]V
for rows.Next() {
err = rows.Scan(c...)
err = rows.Scan(slice.ToAnySlice(c)...)
if err != nil {
return
}
v := make(map[string]any)
v := make(map[string]V)
for i, data := range c {
s, ok := data.(*any)
if ok {
ss, ok := (*s).([]uint8)
if ok {
data = string(ss)
}
}
v[columns[i]] = data
v[columns[i]] = *data
}
m = append(m, v)
}
@ -127,6 +90,30 @@ func (r *SqlxQuery) toMapSlice(dest *[]map[string]any, sql string, params ...any
return
}
func GetToMap[V any](db *sqlx.DB, dest *map[string]V, sql string, params ...any) (err error) {
rows := db.QueryRowx(sql, params...)
columns, err := rows.Columns()
if err != nil {
return err
}
columnLen := len(columns)
c := make([]*V, columnLen)
for i, _ := range c {
var a V
c[i] = &a
}
err = rows.Scan(slice.ToAnySlice(c)...)
if err != nil {
return
}
v := make(map[string]V)
for i, data := range c {
v[columns[i]] = *data
}
*dest = v
return
}
func FormatSql(sql string, params ...any) string {
for _, param := range params {
switch param.(type) {