improve gdb/ghttp/gins; fix issue in gstr

This commit is contained in:
John
2019-12-19 15:14:05 +08:00
parent 50018773b7
commit 922e720d63
20 changed files with 817 additions and 251 deletions

View File

@ -21,65 +21,53 @@ var (
Table = "gf_article"
// Model is the model object of gf_article.
Model = &arModel{g.DB("default").Table(Table).Safe()}
// Primary is the primary key name of table gf_article.
Primary = gdb.GetPrimaryKey(new(Entity))
)
// FindOne retrieves and returns a single Entity by a primary key or where conditions by
// Model.Where. The optional parameter <where> is like follows:
// 123, []int{1, 2, 3}, "john", []string{"john", "smith"}
// g.Map{"id": g.Slice{1,2,3}}, g.Map{"id": 1, "name": "john"}, etc.
//
// Note that it differs with Mode.One is that any single where condition parameter will
// be treated as the value of the primary key in FindOne, but a string condition in
// Model.One. That is, if primary key is "id" and given <where> parameter as "123", the
// FindOne function treats it as "id=123", but Model.One treats it as "123", just a string.
// FindOne is a convenience method for Model.FindOne.
// See Model.FindOne.
func FindOne(where ...interface{}) (*Entity, error) {
return Model.One(gdb.GetPrimaryKeyCondition(Primary, where...)...)
return Model.FindOne(where...)
}
// FindAll retrieves and returns multiple Entity by a primary key or where conditions by
// Model.Where. Also see FindOne.
// FindAll is a convenience method for Model.FindAll.
// See Model.FindAll.
func FindAll(where ...interface{}) ([]*Entity, error) {
return Model.All(gdb.GetPrimaryKeyCondition(Primary, where...)...)
return Model.FindAll(where...)
}
// FindValue retrieves and returns single field value by a primary key or where conditions by
// Model.Where. Also see FindOne.
// FindValue is a convenience method for Model.FindValue.
// See Model.FindValue.
func FindValue(fieldsAndWhere ...interface{}) (gdb.Value, error) {
if len(fieldsAndWhere) == 2 {
return Model.Value(append(fieldsAndWhere[0:1], gdb.GetPrimaryKeyCondition(Primary, fieldsAndWhere[1:]...)...)...)
}
return Model.Value(fieldsAndWhere...)
return Model.FindValue(fieldsAndWhere...)
}
// FindCount retrieves and returns the record number by a primary key or where conditions by
// Model.Where. Also see FindOne.
// FindCount is a convenience method for Model.FindCount.
// See Model.FindCount.
func FindCount(where ...interface{}) (int, error) {
return Model.Count(gdb.GetPrimaryKeyCondition(Primary, where...)...)
return Model.FindCount(where...)
}
// Insert is alias of Model.Insert.
// Insert is a convenience method for Model.Insert.
func Insert(data ...interface{}) (result sql.Result, err error) {
return Model.Insert(data...)
}
// Replace is alias of Model.Replace.
// Replace is a convenience method for Model.Replace.
func Replace(data ...interface{}) (result sql.Result, err error) {
return Model.Replace(data...)
}
// Save is alias of Model.Save.
// Save is a convenience method for Model.Save.
func Save(data ...interface{}) (result sql.Result, err error) {
return Model.Save(data...)
}
// Update is alias of Model.Update.
// Update is a convenience method for Model.Update.
func Update(dataAndWhere ...interface{}) (result sql.Result, err error) {
return Model.Update(dataAndWhere...)
}
// Delete is alias of Model.Delete.
// Delete is a convenience method for Model.Delete.
func Delete(where ...interface{}) (result sql.Result, err error) {
return Model.Delete(where...)
}
@ -166,14 +154,14 @@ func (m *arModel) Or(where interface{}, args ...interface{}) *arModel {
return &arModel{m.M.Or(where, args...)}
}
// GroupBy sets the "GROUP BY" statement for the model.
func (m *arModel) GroupBy(groupBy string) *arModel {
return &arModel{m.M.GroupBy(groupBy)}
// Group sets the "GROUP BY" statement for the model.
func (m *arModel) Group(groupBy string) *arModel {
return &arModel{m.M.Group(groupBy)}
}
// OrderBy sets the "ORDER BY" statement for the model.
func (m *arModel) OrderBy(orderBy string) *arModel {
return &arModel{m.M.OrderBy(orderBy)}
// Order sets the "ORDER BY" statement for the model.
func (m *arModel) Order(orderBy string) *arModel {
return &arModel{m.M.Order(orderBy)}
}
// Limit sets the "LIMIT" statement for the model.
@ -190,11 +178,11 @@ func (m *arModel) Offset(offset int) *arModel {
return &arModel{m.M.Offset(offset)}
}
// ForPage sets the paging number for the model.
// Page sets the paging number for the model.
// The parameter <page> is started from 1 for paging.
// Note that, it differs that the Limit function start from 0 for "LIMIT" statement.
func (m *arModel) ForPage(page, limit int) *arModel {
return &arModel{m.M.ForPage(page, limit)}
func (m *arModel) Page(page, limit int) *arModel {
return &arModel{m.M.Page(page, limit)}
}
// Batch sets the batch operation number for the model.
@ -321,6 +309,46 @@ func (m *arModel) Value(fieldsAndWhere ...interface{}) (gdb.Value, error) {
return m.M.Value(fieldsAndWhere...)
}
// FindOne retrieves and returns a single Record by Model.WherePri and Model.One.
// Also see Model.WherePri and Model.One.
func (m *arModel) FindOne(where ...interface{}) (*Entity, error) {
one, err := m.M.FindOne(where...)
if err != nil {
return nil, err
}
var entity *Entity
if err = one.Struct(&entity); err != nil && err != sql.ErrNoRows {
return nil, err
}
return entity, nil
}
// FindAll retrieves and returns Result by by Model.WherePri and Model.All.
// Also see Model.WherePri and Model.All.
func (m *arModel) FindAll(where ...interface{}) ([]*Entity, error) {
all, err := m.M.FindAll(where...)
if err != nil {
return nil, err
}
var entities []*Entity
if err = all.Structs(&entities); err != nil && err != sql.ErrNoRows {
return nil, err
}
return entities, nil
}
// FindValue retrieves and returns single field value by Model.WherePri and Model.Value.
// Also see Model.WherePri and Model.Value.
func (m *arModel) FindValue(fieldsAndWhere ...interface{}) (gdb.Value, error) {
return m.M.FindValue(fieldsAndWhere...)
}
// FindCount retrieves and returns the record number by Model.WherePri and Model.Count.
// Also see Model.WherePri and Model.Count.
func (m *arModel) FindCount(where ...interface{}) (int, error) {
return m.M.FindCount(where...)
}
// Chunk iterates the table with given size and callback function.
func (m *arModel) Chunk(limit int, callback func(entities []*Entity, err error) bool) {
m.M.Chunk(limit, func(result gdb.Result, err error) bool {

View File

@ -1,48 +1,13 @@
package main
import (
"container/list"
"fmt"
"github.com/gogf/gf/container/garray"
"github.com/gogf/gf/container/glist"
"github.com/gogf/gf/text/gstr"
)
func main() {
// concurrent-safe list.
l := glist.NewFrom(garray.NewArrayRange(1, 10, 1).Slice(), true)
// iterate reading from head.
l.RLockFunc(func(list *list.List) {
length := list.Len()
if length > 0 {
for i, e := 0, list.Front(); i < length; i, e = i+1, e.Next() {
fmt.Print(e.Value)
}
}
})
fmt.Println()
// iterate reading from tail.
l.RLockFunc(func(list *list.List) {
length := list.Len()
if length > 0 {
for i, e := 0, list.Back(); i < length; i, e = i+1, e.Prev() {
fmt.Print(e.Value)
}
}
})
fmt.Println()
// iterate writing from head.
l.LockFunc(func(list *list.List) {
length := list.Len()
if length > 0 {
for i, e := 0, list.Front(); i < length; i, e = i+1, e.Next() {
if e.Value == 6 {
e.Value = "M"
break
}
}
}
})
fmt.Println(l)
a := "aaaaa_post"
b := "aaaaa_"
c := gstr.TrimLeftStr(a, b)
fmt.Println(c)
}

View File

@ -222,7 +222,7 @@ func New(name ...string) (db DB, err error) {
return nil, err
}
} else {
return nil, errors.New(fmt.Sprintf("empty database configuration for item name '%s'", group))
return nil, errors.New(fmt.Sprintf(`database configuration node "%s" is not found`, group))
}
}

View File

@ -156,7 +156,6 @@ func GetPrimaryKeyCondition(primary string, where ...interface{}) (newWhereCondi
}
}
return where
}
// 获得orm标签与属性的映射关系

View File

@ -10,14 +10,13 @@ import (
"database/sql"
"errors"
"fmt"
"github.com/gogf/gf/container/gmap"
"reflect"
"time"
"github.com/gogf/gf/container/gset"
"github.com/gogf/gf/text/gstr"
"github.com/gogf/gf/container/gmap"
"github.com/gogf/gf/util/gconv"
)
@ -289,6 +288,18 @@ func (m *Model) Where(where interface{}, args ...interface{}) *Model {
return model
}
// WherePri does the same logic as Model.Where except that if the parameter <where>
// is a single condition like int/string/float/slice, it treats the condition as the primary
// key value. That is, if primary key is "id" and given <where> parameter as "123", the
// WherePri function treats it as "id=123", but Model.Where treats it as string "123".
func (m *Model) WherePri(where interface{}, args ...interface{}) *Model {
if len(args) > 0 {
return m.Where(where, args...)
}
newWhere := GetPrimaryKeyCondition(m.getPrimaryKey(), where)
return m.Where(newWhere[0], newWhere[1:]...)
}
// And adds "AND" condition to the where statement.
func (m *Model) And(where interface{}, args ...interface{}) *Model {
model := m.getModel()
@ -317,20 +328,34 @@ func (m *Model) Or(where interface{}, args ...interface{}) *Model {
return model
}
// GroupBy sets the "GROUP BY" statement for the model.
func (m *Model) GroupBy(groupBy string) *Model {
// Group sets the "GROUP BY" statement for the model.
func (m *Model) Group(groupBy string) *Model {
model := m.getModel()
model.groupBy = m.db.quoteString(groupBy)
return model
}
// OrderBy sets the "ORDER BY" statement for the model.
func (m *Model) OrderBy(orderBy string) *Model {
// GroupBy is alias of Model.Group.
// See Model.Group.
// Deprecated.
func (m *Model) GroupBy(groupBy string) *Model {
return m.Group(groupBy)
}
// Order sets the "ORDER BY" statement for the model.
func (m *Model) Order(orderBy string) *Model {
model := m.getModel()
model.orderBy = m.db.quoteString(orderBy)
return model
}
// OrderBy is alias of Model.Order.
// See Model.Order.
// Deprecated.
func (m *Model) OrderBy(orderBy string) *Model {
return m.Order(orderBy)
}
// Limit sets the "LIMIT" statement for the model.
// The parameter <limit> can be either one or two number, if passed two number is passed,
// it then sets "LIMIT limit[0],limit[1]" statement for the model, or else it sets "LIMIT limit[0]"
@ -355,16 +380,23 @@ func (m *Model) Offset(offset int) *Model {
return model
}
// ForPage sets the paging number for the model.
// Page sets the paging number for the model.
// The parameter <page> is started from 1 for paging.
// Note that, it differs that the Limit function start from 0 for "LIMIT" statement.
func (m *Model) ForPage(page, limit int) *Model {
func (m *Model) Page(page, limit int) *Model {
model := m.getModel()
model.start = (page - 1) * limit
model.limit = limit
return model
}
// ForPage is alias of Model.Page.
// See Model.Page.
// Deprecated.
func (m *Model) ForPage(page, limit int) *Model {
return m.Page(page, limit)
}
// Batch sets the batch operation number for the model.
func (m *Model) Batch(batch int) *Model {
model := m.getModel()
@ -446,50 +478,6 @@ func (m *Model) Data(data ...interface{}) *Model {
return model
}
// filterDataForInsertOrUpdate does filter feature with data for inserting/updating operations.
// Note that, it does not filter list item, which is also type of map, for "omit empty" feature.
func (m *Model) filterDataForInsertOrUpdate(data interface{}) interface{} {
if list, ok := m.data.(List); ok {
for k, item := range list {
list[k] = m.doFilterDataMapForInsertOrUpdate(item, false)
}
return list
} else if item, ok := m.data.(Map); ok {
return m.doFilterDataMapForInsertOrUpdate(item, true)
}
return data
}
// doFilterDataMapForInsertOrUpdate does the filter features for map.
// Note that, it does not filter list item, which is also type of map, for "omit empty" feature.
func (m *Model) doFilterDataMapForInsertOrUpdate(data Map, allowOmitEmpty bool) Map {
if m.filter {
data = m.db.filterFields(m.tables, data)
}
// Remove key-value pairs of which the value is empty.
if allowOmitEmpty && m.option&OPTION_OMITEMPTY > 0 {
m := gmap.NewStrAnyMapFrom(data)
m.FilterEmpty()
data = m.Map()
}
if len(m.fields) > 0 && m.fields != "*" {
// Keep specified fields.
set := gset.NewStrSetFrom(gstr.SplitAndTrim(m.fields, ","))
for k := range data {
if !set.Contains(k) {
delete(data, k)
}
}
} else if len(m.fieldsEx) > 0 {
// Filter specified fields.
for _, v := range gstr.SplitAndTrim(m.fieldsEx, ",") {
delete(data, v)
}
}
return data
}
// Insert does "INSERT INTO ..." statement for the model.
// The optional parameter <data> is the same as the parameter of Model.Data function,
// see Model.Data.
@ -637,7 +625,7 @@ func (m *Model) Update(dataAndWhere ...interface{}) (result sql.Result, err erro
if m.data == nil {
return nil, errors.New("updating table with empty data")
}
condition, conditionArgs := m.formatCondition()
condition, conditionArgs := m.formatCondition(false)
return m.db.doUpdate(
m.getLink(),
m.tables,
@ -659,7 +647,7 @@ func (m *Model) Delete(where ...interface{}) (result sql.Result, err error) {
m.checkAndRemoveCache()
}
}()
condition, conditionArgs := m.formatCondition()
condition, conditionArgs := m.formatCondition(false)
return m.db.doDelete(m.getLink(), m.tables, condition, conditionArgs...)
}
@ -680,7 +668,7 @@ func (m *Model) All(where ...interface{}) (Result, error) {
if len(where) > 0 {
return m.Where(where[0], where[1:]...).All()
}
condition, conditionArgs := m.formatCondition()
condition, conditionArgs := m.formatCondition(false)
return m.getAll(fmt.Sprintf("SELECT %s FROM %s%s", m.fields, m.tables, condition), conditionArgs...)
}
@ -690,12 +678,16 @@ func (m *Model) All(where ...interface{}) (Result, error) {
// The optional parameter <where> is the same as the parameter of Model.Where function,
// see Model.Where.
func (m *Model) One(where ...interface{}) (Record, error) {
list, err := m.All(where...)
if len(where) > 0 {
return m.Where(where[0], where[1:]...).One()
}
condition, conditionArgs := m.formatCondition(true)
all, err := m.getAll(fmt.Sprintf("SELECT %s FROM %s%s", m.fields, m.tables, condition), conditionArgs...)
if err != nil {
return nil, err
}
if len(list) > 0 {
return list[0], nil
if len(all) > 0 {
return all[0], nil
}
return nil, nil
}
@ -833,7 +825,7 @@ func (m *Model) Count(where ...interface{}) (int, error) {
} else {
m.fields = fmt.Sprintf(`COUNT(%s)`, m.fields)
}
condition, conditionArgs := m.formatCondition()
condition, conditionArgs := m.formatCondition(false)
s := fmt.Sprintf("SELECT %s FROM %s %s", m.fields, m.tables, condition)
if len(m.groupBy) > 0 {
s = fmt.Sprintf("SELECT COUNT(1) FROM (%s) count_alias", s)
@ -850,6 +842,116 @@ func (m *Model) Count(where ...interface{}) (int, error) {
return 0, nil
}
// FindOne retrieves and returns a single Record by Model.WherePri and Model.One.
// Also see Model.WherePri and Model.One.
func (m *Model) FindOne(where ...interface{}) (Record, error) {
if len(where) > 0 {
return m.WherePri(where[0], where[1:]...).One()
}
return m.One()
}
// FindAll retrieves and returns Result by by Model.WherePri and Model.All.
// Also see Model.WherePri and Model.All.
func (m *Model) FindAll(where ...interface{}) (Result, error) {
if len(where) > 0 {
return m.WherePri(where[0], where[1:]...).All()
}
return m.All()
}
// FindValue retrieves and returns single field value by Model.WherePri and Model.Value.
// Also see Model.WherePri and Model.Value.
func (m *Model) FindValue(fieldsAndWhere ...interface{}) (Value, error) {
if len(fieldsAndWhere) >= 2 {
return m.WherePri(fieldsAndWhere[1], fieldsAndWhere[2:]...).Fields(gconv.String(fieldsAndWhere[0])).Value()
}
if len(fieldsAndWhere) == 1 {
return m.Fields(gconv.String(fieldsAndWhere[0])).Value()
}
return m.Value()
}
// FindCount retrieves and returns the record number by Model.WherePri and Model.Count.
// Also see Model.WherePri and Model.Count.
func (m *Model) FindCount(where ...interface{}) (int, error) {
if len(where) > 0 {
return m.WherePri(where[0], where[1:]...).Count()
}
return m.Count()
}
// Chunk iterates the table with given size and callback function.
func (m *Model) Chunk(limit int, callback func(result Result, err error) bool) {
page := m.start
if page == 0 {
page = 1
}
model := m
for {
model = model.Page(page, limit)
data, err := model.All()
if err != nil {
callback(nil, err)
break
}
if len(data) == 0 {
break
}
if callback(data, err) == false {
break
}
if len(data) < limit {
break
}
page++
}
}
// filterDataForInsertOrUpdate does filter feature with data for inserting/updating operations.
// Note that, it does not filter list item, which is also type of map, for "omit empty" feature.
func (m *Model) filterDataForInsertOrUpdate(data interface{}) interface{} {
if list, ok := m.data.(List); ok {
for k, item := range list {
list[k] = m.doFilterDataMapForInsertOrUpdate(item, false)
}
return list
} else if item, ok := m.data.(Map); ok {
return m.doFilterDataMapForInsertOrUpdate(item, true)
}
return data
}
// doFilterDataMapForInsertOrUpdate does the filter features for map.
// Note that, it does not filter list item, which is also type of map, for "omit empty" feature.
func (m *Model) doFilterDataMapForInsertOrUpdate(data Map, allowOmitEmpty bool) Map {
if m.filter {
data = m.db.filterFields(m.tables, data)
}
// Remove key-value pairs of which the value is empty.
if allowOmitEmpty && m.option&OPTION_OMITEMPTY > 0 {
m := gmap.NewStrAnyMapFrom(data)
m.FilterEmpty()
data = m.Map()
}
if len(m.fields) > 0 && m.fields != "*" {
// Keep specified fields.
set := gset.NewStrSetFrom(gstr.SplitAndTrim(m.fields, ","))
for k := range data {
if !set.Contains(k) {
delete(data, k)
}
}
} else if len(m.fieldsEx) > 0 {
// Filter specified fields.
for _, v := range gstr.SplitAndTrim(m.fieldsEx, ",") {
delete(data, v)
}
}
return data
}
// getLink returns the underlying database link object with configured <linkType> attribute.
func (m *Model) getLink() dbLink {
if m.tx != nil {
@ -891,6 +993,23 @@ func (m *Model) getAll(query string, args ...interface{}) (result Result, err er
return result, err
}
// getPrimaryKey retrieves and returns the primary key name of the model table.
// It parses m.tables to retrieve the primary table name, supporting m.tables like:
// "user", "user u", "user as u, user_detail as ud".
func (m *Model) getPrimaryKey() string {
table := gstr.SplitAndTrim(m.tables, " ")[0]
tableFields, err := m.db.TableFields(table)
if err != nil {
return ""
}
for name, field := range tableFields {
if gstr.ContainsI(field.Key, "pri") {
return name
}
}
return ""
}
// checkAndRemoveCache checks and remove the cache if necessary.
func (m *Model) checkAndRemoveCache() {
if m.cacheEnabled && m.cacheDuration < 0 && len(m.cacheName) > 0 {
@ -900,7 +1019,9 @@ func (m *Model) checkAndRemoveCache() {
// formatCondition formats where arguments of the model and returns a new condition sql and its arguments.
// Note that this function does not change any attribute value of the <m>.
func (m *Model) formatCondition() (condition string, conditionArgs []interface{}) {
//
// The parameter <limit> specifies whether limits querying only one record if m.limit is not set.
func (m *Model) formatCondition(limit bool) (condition string, conditionArgs []interface{}) {
var where string
if len(m.whereHolder) > 0 {
for _, v := range m.whereHolder {
@ -955,36 +1076,11 @@ func (m *Model) formatCondition() (condition string, conditionArgs []interface{}
} else {
condition += fmt.Sprintf(" LIMIT %d", m.limit)
}
} else if limit {
condition += " LIMIT 1"
}
if m.offset >= 0 {
condition += fmt.Sprintf(" OFFSET %d", m.offset)
}
return
}
// Chunk iterates the table with given size and callback function.
func (m *Model) Chunk(limit int, callback func(result Result, err error) bool) {
page := m.start
if page == 0 {
page = 1
}
model := m
for {
model = model.ForPage(page, limit)
data, err := model.All()
if err != nil {
callback(nil, err)
break
}
if len(data) == 0 {
break
}
if callback(data, err) == false {
break
}
if len(data) < limit {
break
}
page++
}
}

View File

@ -200,7 +200,7 @@ func Test_Model_Update(t *testing.T) {
defer dropTable(table)
// UPDATE...LIMIT
gtest.Case(t, func() {
result, err := db.Table(table).Data("nickname", "T100").OrderBy("id desc").Limit(2).Update()
result, err := db.Table(table).Data("nickname", "T100").Order("id desc").Limit(2).Update()
gtest.Assert(err, nil)
n, _ := result.RowsAffected()
gtest.Assert(n, 2)
@ -246,10 +246,10 @@ func Test_Model_Clone(t *testing.T) {
count, err := md.Count()
gtest.Assert(err, nil)
record, err := md.OrderBy("id DESC").One()
record, err := md.Order("id DESC").One()
gtest.Assert(err, nil)
result, err := md.OrderBy("id ASC").All()
result, err := md.Order("id ASC").All()
gtest.Assert(err, nil)
gtest.Assert(count, 2)
@ -327,7 +327,7 @@ func Test_Model_Safe(t *testing.T) {
gtest.Assert(err, nil)
gtest.Assert(count, 2)
all, err := md2.OrderBy("id asc").All()
all, err := md2.Order("id asc").All()
gtest.Assert(err, nil)
gtest.Assert(len(all), 2)
gtest.Assert(all[0]["id"].Int(), 1)
@ -342,7 +342,7 @@ func Test_Model_Safe(t *testing.T) {
gtest.Assert(err, nil)
gtest.Assert(count, 3)
all, err = md3.OrderBy("id asc").All()
all, err = md3.Order("id asc").All()
gtest.Assert(err, nil)
gtest.Assert(len(all), 3)
gtest.Assert(all[0]["id"].Int(), 4)
@ -371,6 +371,44 @@ func Test_Model_All(t *testing.T) {
})
}
func Test_Model_FindAll(t *testing.T) {
table := createInitTable()
defer dropTable(table)
gtest.Case(t, func() {
result, err := db.Table(table).FindAll(5)
gtest.Assert(err, nil)
gtest.Assert(len(result), 1)
gtest.Assert(result[0]["id"].Int(), 5)
})
gtest.Case(t, func() {
result, err := db.Table(table).Order("id asc").FindAll("id", 8)
gtest.Assert(err, nil)
gtest.Assert(len(result), 1)
gtest.Assert(result[0]["id"].Int(), 8)
})
gtest.Case(t, func() {
result, err := db.Table(table).Order("id asc").FindAll(g.Slice{3, 9})
gtest.Assert(err, nil)
gtest.Assert(len(result), 2)
gtest.Assert(result[0]["id"].Int(), 3)
gtest.Assert(result[1]["id"].Int(), 9)
})
gtest.Case(t, func() {
result, err := db.Table(table).FindAll()
gtest.Assert(err, nil)
gtest.Assert(len(result), INIT_DATA_SIZE)
})
gtest.Case(t, func() {
result, err := db.Table(table).Where("id<0").FindAll()
gtest.Assert(result, nil)
gtest.Assert(err, nil)
})
}
func Test_Model_One(t *testing.T) {
table := createInitTable()
defer dropTable(table)
@ -387,9 +425,45 @@ func Test_Model_One(t *testing.T) {
})
}
func Test_Model_FindOne(t *testing.T) {
table := createInitTable()
defer dropTable(table)
gtest.Case(t, func() {
record, err := db.Table(table).FindOne(1)
gtest.Assert(err, nil)
gtest.Assert(record["nickname"].String(), "name_1")
})
gtest.Case(t, func() {
record, err := db.Table(table).FindOne(3)
gtest.Assert(err, nil)
gtest.Assert(record["nickname"].String(), "name_3")
})
gtest.Case(t, func() {
record, err := db.Table(table).Where("id", 1).FindOne()
gtest.Assert(err, nil)
gtest.Assert(record["nickname"].String(), "name_1")
})
gtest.Case(t, func() {
record, err := db.Table(table).FindOne("id", 9)
gtest.Assert(err, nil)
gtest.Assert(record["nickname"].String(), "name_9")
})
gtest.Case(t, func() {
record, err := db.Table(table).Where("id", 0).FindOne()
gtest.Assert(err, nil)
gtest.Assert(record, nil)
})
}
func Test_Model_Value(t *testing.T) {
table := createInitTable()
defer dropTable(table)
gtest.Case(t, func() {
value, err := db.Table(table).Fields("nickname").Where("id", 1).Value()
gtest.Assert(err, nil)
@ -403,6 +477,35 @@ func Test_Model_Value(t *testing.T) {
})
}
func Test_Model_FindValue(t *testing.T) {
table := createInitTable()
defer dropTable(table)
gtest.Case(t, func() {
value, err := db.Table(table).FindValue("nickname", 1)
gtest.Assert(err, nil)
gtest.Assert(value.String(), "name_1")
})
gtest.Case(t, func() {
value, err := db.Table(table).Order("id desc").FindValue("nickname")
gtest.Assert(err, nil)
gtest.Assert(value.String(), "name_10")
})
gtest.Case(t, func() {
value, err := db.Table(table).Fields("nickname").Where("id", 1).FindValue()
gtest.Assert(err, nil)
gtest.Assert(value.String(), "name_1")
})
gtest.Case(t, func() {
value, err := db.Table(table).Fields("nickname").Where("id", 0).FindValue()
gtest.Assert(err, nil)
gtest.Assert(value, nil)
})
}
func Test_Model_Count(t *testing.T) {
table := createInitTable()
defer dropTable(table)
@ -413,6 +516,26 @@ func Test_Model_Count(t *testing.T) {
})
}
func Test_Model_FindCount(t *testing.T) {
table := createInitTable()
defer dropTable(table)
gtest.Case(t, func() {
count, err := db.Table(table).FindCount(g.Slice{1, 3})
gtest.Assert(err, nil)
gtest.Assert(count, 2)
})
gtest.Case(t, func() {
count, err := db.Table(table).FindCount(g.Slice{1, 300000})
gtest.Assert(err, nil)
gtest.Assert(count, 1)
})
gtest.Case(t, func() {
count, err := db.Table(table).FindCount()
gtest.Assert(err, nil)
gtest.Assert(count, INIT_DATA_SIZE)
})
}
func Test_Model_Select(t *testing.T) {
table := createInitTable()
defer dropTable(table)
@ -514,7 +637,7 @@ func Test_Model_Structs(t *testing.T) {
CreateTime gtime.Time
}
var users []User
err := db.Table(table).OrderBy("id asc").Structs(&users)
err := db.Table(table).Order("id asc").Structs(&users)
if err != nil {
gtest.Error(err)
}
@ -537,7 +660,7 @@ func Test_Model_Structs(t *testing.T) {
CreateTime *gtime.Time
}
var users []*User
err := db.Table(table).OrderBy("id asc").Structs(&users)
err := db.Table(table).Order("id asc").Structs(&users)
if err != nil {
gtest.Error(err)
}
@ -560,7 +683,7 @@ func Test_Model_Structs(t *testing.T) {
CreateTime *gtime.Time
}
var users []*User
err := db.Table(table).OrderBy("id asc").Scan(&users)
err := db.Table(table).Order("id asc").Scan(&users)
if err != nil {
gtest.Error(err)
}
@ -629,7 +752,7 @@ func Test_Model_Scan(t *testing.T) {
CreateTime gtime.Time
}
var users []User
err := db.Table(table).OrderBy("id asc").Scan(&users)
err := db.Table(table).Order("id asc").Scan(&users)
gtest.Assert(err, nil)
gtest.Assert(len(users), INIT_DATA_SIZE)
gtest.Assert(users[0].Id, 1)
@ -649,7 +772,7 @@ func Test_Model_Scan(t *testing.T) {
CreateTime *gtime.Time
}
var users []*User
err := db.Table(table).OrderBy("id asc").Scan(&users)
err := db.Table(table).Order("id asc").Scan(&users)
gtest.Assert(err, nil)
gtest.Assert(len(users), INIT_DATA_SIZE)
gtest.Assert(users[0].Id, 1)
@ -683,7 +806,7 @@ func Test_Model_OrderBy(t *testing.T) {
defer dropTable(table)
gtest.Case(t, func() {
result, err := db.Table(table).OrderBy("id DESC").Select()
result, err := db.Table(table).Order("id DESC").Select()
gtest.Assert(err, nil)
gtest.Assert(len(result), INIT_DATA_SIZE)
gtest.Assert(result[0]["nickname"].String(), fmt.Sprintf("name_%d", INIT_DATA_SIZE))
@ -724,7 +847,7 @@ func Test_Model_Where(t *testing.T) {
gtest.Case(t, func() {
result, err := db.Table(table).Where(g.Map{
"passport like": "user_1%",
}).OrderBy("id asc").All()
}).Order("id asc").All()
gtest.Assert(err, nil)
gtest.Assert(len(result), 2)
gtest.Assert(result[0].GMap().Get("id"), 1)
@ -870,7 +993,7 @@ func Test_Model_Where(t *testing.T) {
"create_time > 0": nil,
"id": g.Slice{1, 2, 3},
}
result, err := db.Table(table).Where(conditions).OrderBy("id asc").All()
result, err := db.Table(table).Where(conditions).Order("id asc").All()
gtest.Assert(err, nil)
gtest.Assert(len(result), 3)
gtest.Assert(result[0]["id"].Int(), 1)
@ -885,7 +1008,7 @@ func Test_Model_Where(t *testing.T) {
"create_time > ?": 0,
"id in(?)": g.Slice{1, 2, 3},
}
result, err := db.Table(table).Where(conditions).OrderBy("id asc").All()
result, err := db.Table(table).Where(conditions).Order("id asc").All()
gtest.Assert(err, nil)
gtest.Assert(len(result), 3)
gtest.Assert(result[0]["id"].Int(), 1)
@ -906,7 +1029,7 @@ func Test_Model_Where(t *testing.T) {
})
// slice single
gtest.Case(t, func() {
result, err := db.Table(table).Where("id IN(?)", g.Slice{1, 3}).OrderBy("id ASC").All()
result, err := db.Table(table).Where("id IN(?)", g.Slice{1, 3}).Order("id ASC").All()
gtest.Assert(err, nil)
gtest.Assert(len(result), 2)
gtest.Assert(result[0]["id"].Int(), 1)
@ -914,7 +1037,7 @@ func Test_Model_Where(t *testing.T) {
})
// slice + string
gtest.Case(t, func() {
result, err := db.Table(table).Where("nickname=? AND id IN(?)", "name_3", g.Slice{1, 3}).OrderBy("id ASC").All()
result, err := db.Table(table).Where("nickname=? AND id IN(?)", "name_3", g.Slice{1, 3}).Order("id ASC").All()
gtest.Assert(err, nil)
gtest.Assert(len(result), 1)
gtest.Assert(result[0]["id"].Int(), 3)
@ -924,7 +1047,7 @@ func Test_Model_Where(t *testing.T) {
result, err := db.Table(table).Where(g.Map{
"id": g.Slice{1, 3},
"nickname": "name_3",
}).OrderBy("id ASC").All()
}).Order("id ASC").All()
gtest.Assert(err, nil)
gtest.Assert(len(result), 1)
gtest.Assert(result[0]["id"].Int(), 3)
@ -938,7 +1061,265 @@ func Test_Model_Where(t *testing.T) {
result, err := db.Table(table).Where(User{
Ids: []int{1, 3},
Nickname: "name_3",
}).OrderBy("id ASC").All()
}).Order("id ASC").All()
gtest.Assert(err, nil)
gtest.Assert(len(result), 1)
gtest.Assert(result[0]["id"].Int(), 3)
})
}
func Test_Model_WherePri(t *testing.T) {
table := createInitTable()
defer dropTable(table)
// primary key
gtest.Case(t, func() {
one, err := db.Table(table).WherePri(3).One()
gtest.Assert(err, nil)
gtest.AssertNE(one, nil)
gtest.Assert(one["id"].Int(), 3)
})
gtest.Case(t, func() {
all, err := db.Table(table).WherePri(g.Slice{3, 9}).Order("id asc").All()
gtest.Assert(err, nil)
gtest.Assert(len(all), 2)
gtest.Assert(all[0]["id"].Int(), 3)
gtest.Assert(all[1]["id"].Int(), 9)
})
// string
gtest.Case(t, func() {
result, err := db.Table(table).WherePri("id=? and nickname=?", 3, "name_3").One()
gtest.Assert(err, nil)
gtest.AssertGT(len(result), 0)
gtest.Assert(result["id"].Int(), 3)
})
// slice parameter
gtest.Case(t, func() {
result, err := db.Table(table).WherePri("id=? and nickname=?", g.Slice{3, "name_3"}).One()
gtest.Assert(err, nil)
gtest.AssertGT(len(result), 0)
gtest.Assert(result["id"].Int(), 3)
})
// map like
gtest.Case(t, func() {
result, err := db.Table(table).WherePri(g.Map{
"passport like": "user_1%",
}).Order("id asc").All()
gtest.Assert(err, nil)
gtest.Assert(len(result), 2)
gtest.Assert(result[0].GMap().Get("id"), 1)
gtest.Assert(result[1].GMap().Get("id"), 10)
})
// map + slice parameter
gtest.Case(t, func() {
result, err := db.Table(table).WherePri(g.Map{
"id": g.Slice{1, 2, 3},
"passport": g.Slice{"user_2", "user_3"},
}).And("id=? and nickname=?", g.Slice{3, "name_3"}).One()
gtest.Assert(err, nil)
gtest.AssertGT(len(result), 0)
gtest.Assert(result["id"].Int(), 3)
})
gtest.Case(t, func() {
result, err := db.Table(table).WherePri(g.Map{
"id": g.Slice{1, 2, 3},
"passport": g.Slice{"user_2", "user_3"},
}).Or("nickname=?", g.Slice{"name_4"}).And("id", 3).One()
gtest.Assert(err, nil)
gtest.AssertGT(len(result), 0)
gtest.Assert(result["id"].Int(), 3)
})
gtest.Case(t, func() {
result, err := db.Table(table).WherePri("id=3", g.Slice{}).One()
gtest.Assert(err, nil)
gtest.AssertGT(len(result), 0)
gtest.Assert(result["id"].Int(), 3)
})
gtest.Case(t, func() {
result, err := db.Table(table).WherePri("id=?", g.Slice{3}).One()
gtest.Assert(err, nil)
gtest.AssertGT(len(result), 0)
gtest.Assert(result["id"].Int(), 3)
})
gtest.Case(t, func() {
result, err := db.Table(table).WherePri("id", 3).One()
gtest.Assert(err, nil)
gtest.AssertGT(len(result), 0)
gtest.Assert(result["id"].Int(), 3)
})
gtest.Case(t, func() {
result, err := db.Table(table).WherePri("id", 3).WherePri("nickname", "name_3").One()
gtest.Assert(err, nil)
gtest.Assert(result["id"].Int(), 3)
})
gtest.Case(t, func() {
result, err := db.Table(table).WherePri("id", 3).And("nickname", "name_3").One()
gtest.Assert(err, nil)
gtest.Assert(result["id"].Int(), 3)
})
gtest.Case(t, func() {
result, err := db.Table(table).WherePri("id", 30).Or("nickname", "name_3").One()
gtest.Assert(err, nil)
gtest.Assert(result["id"].Int(), 3)
})
gtest.Case(t, func() {
result, err := db.Table(table).WherePri("id", 30).Or("nickname", "name_3").And("id>?", 1).One()
gtest.Assert(err, nil)
gtest.Assert(result["id"].Int(), 3)
})
gtest.Case(t, func() {
result, err := db.Table(table).WherePri("id", 30).Or("nickname", "name_3").And("id>", 1).One()
gtest.Assert(err, nil)
gtest.Assert(result["id"].Int(), 3)
})
// slice
gtest.Case(t, func() {
result, err := db.Table(table).WherePri("id=? AND nickname=?", g.Slice{3, "name_3"}...).One()
gtest.Assert(err, nil)
gtest.Assert(result["id"].Int(), 3)
})
gtest.Case(t, func() {
result, err := db.Table(table).WherePri("id=? AND nickname=?", g.Slice{3, "name_3"}).One()
gtest.Assert(err, nil)
gtest.Assert(result["id"].Int(), 3)
})
gtest.Case(t, func() {
result, err := db.Table(table).WherePri("passport like ? and nickname like ?", g.Slice{"user_3", "name_3"}).One()
gtest.Assert(err, nil)
gtest.Assert(result["id"].Int(), 3)
})
// map
gtest.Case(t, func() {
result, err := db.Table(table).WherePri(g.Map{"id": 3, "nickname": "name_3"}).One()
gtest.Assert(err, nil)
gtest.Assert(result["id"].Int(), 3)
})
// map key operator
gtest.Case(t, func() {
result, err := db.Table(table).WherePri(g.Map{"id>": 1, "id<": 3}).One()
gtest.Assert(err, nil)
gtest.Assert(result["id"].Int(), 2)
})
// gmap.Map
gtest.Case(t, func() {
result, err := db.Table(table).WherePri(gmap.NewFrom(g.MapAnyAny{"id": 3, "nickname": "name_3"})).One()
gtest.Assert(err, nil)
gtest.Assert(result["id"].Int(), 3)
})
// gmap.Map key operator
gtest.Case(t, func() {
result, err := db.Table(table).WherePri(gmap.NewFrom(g.MapAnyAny{"id>": 1, "id<": 3})).One()
gtest.Assert(err, nil)
gtest.Assert(result["id"].Int(), 2)
})
// list map
gtest.Case(t, func() {
result, err := db.Table(table).WherePri(gmap.NewListMapFrom(g.MapAnyAny{"id": 3, "nickname": "name_3"})).One()
gtest.Assert(err, nil)
gtest.Assert(result["id"].Int(), 3)
})
// list map key operator
gtest.Case(t, func() {
result, err := db.Table(table).WherePri(gmap.NewListMapFrom(g.MapAnyAny{"id>": 1, "id<": 3})).One()
gtest.Assert(err, nil)
gtest.Assert(result["id"].Int(), 2)
})
// tree map
gtest.Case(t, func() {
result, err := db.Table(table).WherePri(gmap.NewTreeMapFrom(gutil.ComparatorString, g.MapAnyAny{"id": 3, "nickname": "name_3"})).One()
gtest.Assert(err, nil)
gtest.Assert(result["id"].Int(), 3)
})
// tree map key operator
gtest.Case(t, func() {
result, err := db.Table(table).WherePri(gmap.NewTreeMapFrom(gutil.ComparatorString, g.MapAnyAny{"id>": 1, "id<": 3})).One()
gtest.Assert(err, nil)
gtest.Assert(result["id"].Int(), 2)
})
// complicated where 1
gtest.Case(t, func() {
//db.SetDebug(true)
conditions := g.Map{
"nickname like ?": "%name%",
"id between ? and ?": g.Slice{1, 3},
"id > 0": nil,
"create_time > 0": nil,
"id": g.Slice{1, 2, 3},
}
result, err := db.Table(table).WherePri(conditions).Order("id asc").All()
gtest.Assert(err, nil)
gtest.Assert(len(result), 3)
gtest.Assert(result[0]["id"].Int(), 1)
})
// complicated where 2
gtest.Case(t, func() {
//db.SetDebug(true)
conditions := g.Map{
"nickname like ?": "%name%",
"id between ? and ?": g.Slice{1, 3},
"id >= ?": 1,
"create_time > ?": 0,
"id in(?)": g.Slice{1, 2, 3},
}
result, err := db.Table(table).WherePri(conditions).Order("id asc").All()
gtest.Assert(err, nil)
gtest.Assert(len(result), 3)
gtest.Assert(result[0]["id"].Int(), 1)
})
// struct
gtest.Case(t, func() {
type User struct {
Id int `json:"id"`
Nickname string `gconv:"nickname"`
}
result, err := db.Table(table).WherePri(User{3, "name_3"}).One()
gtest.Assert(err, nil)
gtest.Assert(result["id"].Int(), 3)
result, err = db.Table(table).WherePri(&User{3, "name_3"}).One()
gtest.Assert(err, nil)
gtest.Assert(result["id"].Int(), 3)
})
// slice single
gtest.Case(t, func() {
result, err := db.Table(table).WherePri("id IN(?)", g.Slice{1, 3}).Order("id ASC").All()
gtest.Assert(err, nil)
gtest.Assert(len(result), 2)
gtest.Assert(result[0]["id"].Int(), 1)
gtest.Assert(result[1]["id"].Int(), 3)
})
// slice + string
gtest.Case(t, func() {
result, err := db.Table(table).WherePri("nickname=? AND id IN(?)", "name_3", g.Slice{1, 3}).Order("id ASC").All()
gtest.Assert(err, nil)
gtest.Assert(len(result), 1)
gtest.Assert(result[0]["id"].Int(), 3)
})
// slice + map
gtest.Case(t, func() {
result, err := db.Table(table).WherePri(g.Map{
"id": g.Slice{1, 3},
"nickname": "name_3",
}).Order("id ASC").All()
gtest.Assert(err, nil)
gtest.Assert(len(result), 1)
gtest.Assert(result[0]["id"].Int(), 3)
})
// slice + struct
gtest.Case(t, func() {
type User struct {
Ids []int `json:"id"`
Nickname string `gconv:"nickname"`
}
result, err := db.Table(table).WherePri(User{
Ids: []int{1, 3},
Nickname: "name_3",
}).Order("id ASC").All()
gtest.Assert(err, nil)
gtest.Assert(len(result), 1)
gtest.Assert(result[0]["id"].Int(), 3)
@ -969,7 +1350,7 @@ func Test_Model_Offset(t *testing.T) {
table := createInitTable()
defer dropTable(table)
result, err := db.Table(table).Limit(2).Offset(5).OrderBy("id").Select()
result, err := db.Table(table).Limit(2).Offset(5).Order("id").Select()
gtest.Assert(err, nil)
gtest.Assert(len(result), 2)
gtest.Assert(result[0]["id"], 6)
@ -980,7 +1361,7 @@ func Test_Model_ForPage(t *testing.T) {
table := createInitTable()
defer dropTable(table)
result, err := db.Table(table).ForPage(3, 3).OrderBy("id").Select()
result, err := db.Table(table).ForPage(3, 3).Order("id").Select()
gtest.Assert(err, nil)
gtest.Assert(len(result), 3)
gtest.Assert(result[0]["id"], 7)
@ -1153,7 +1534,7 @@ func Test_Model_Option_List(t *testing.T) {
gtest.Assert(err, nil)
n, _ := r.RowsAffected()
gtest.Assert(n, 2)
list, err := db.Table(table).OrderBy("id asc").All()
list, err := db.Table(table).Order("id asc").All()
gtest.Assert(err, nil)
gtest.Assert(len(list), 2)
gtest.Assert(list[0]["id"].String(), "1")
@ -1187,7 +1568,7 @@ func Test_Model_Option_List(t *testing.T) {
gtest.Assert(err, nil)
n, _ := r.RowsAffected()
gtest.Assert(n, 2)
list, err := db.Table(table).OrderBy("id asc").All()
list, err := db.Table(table).Order("id asc").All()
g.Dump(list)
gtest.Assert(err, nil)
gtest.Assert(len(list), 2)
@ -1232,7 +1613,7 @@ func Test_Model_FieldsEx(t *testing.T) {
defer dropTable(table)
// Select.
gtest.Case(t, func() {
r, err := db.Table(table).FieldsEx("create_time, id").Where("id in (?)", g.Slice{1, 2}).OrderBy("id asc").All()
r, err := db.Table(table).FieldsEx("create_time, id").Where("id in (?)", g.Slice{1, 2}).Order("id asc").All()
gtest.Assert(err, nil)
gtest.Assert(len(r), 2)
gtest.Assert(len(r[0]), 3)
@ -1268,7 +1649,7 @@ func Test_Model_Prefix(t *testing.T) {
defer dropTable(PREFIX1 + table)
// Select.
gtest.Case(t, func() {
r, err := db.Table(table).Where("id in (?)", g.Slice{1, 2}).OrderBy("id asc").All()
r, err := db.Table(table).Where("id in (?)", g.Slice{1, 2}).Order("id asc").All()
gtest.Assert(err, nil)
gtest.Assert(len(r), 2)
gtest.Assert(r[0]["id"], "1")
@ -1276,7 +1657,7 @@ func Test_Model_Prefix(t *testing.T) {
})
// Select with alias.
gtest.Case(t, func() {
r, err := db.Table(table+" as u").Where("u.id in (?)", g.Slice{1, 2}).OrderBy("u.id asc").All()
r, err := db.Table(table+" as u").Where("u.id in (?)", g.Slice{1, 2}).Order("u.id asc").All()
gtest.Assert(err, nil)
gtest.Assert(len(r), 2)
gtest.Assert(r[0]["id"], "1")
@ -1284,7 +1665,7 @@ func Test_Model_Prefix(t *testing.T) {
})
// Select with alias and join statement.
gtest.Case(t, func() {
r, err := db.Table(table+" as u1").LeftJoin(table+" as u2", "u2.id=u1.id").Where("u1.id in (?)", g.Slice{1, 2}).OrderBy("u1.id asc").All()
r, err := db.Table(table+" as u1").LeftJoin(table+" as u2", "u2.id=u1.id").Where("u1.id in (?)", g.Slice{1, 2}).Order("u1.id asc").All()
gtest.Assert(err, nil)
gtest.Assert(len(r), 2)
gtest.Assert(r[0]["id"], "1")

View File

@ -5,6 +5,9 @@
// You can obtain one at https://github.com/gogf/gf.
// Package gins provides instances and core components management.
//
// Note that it should not used glog.Panic* functions for panics if you do not want
// to log all the panics.
package gins
import (
@ -103,7 +106,7 @@ func View(name ...string) *gview.View {
}
if m != nil {
if err := view.SetConfigWithMap(m); err != nil {
glog.Panic(err)
panic(err)
}
}
}
@ -150,7 +153,7 @@ func Log(name ...string) *glog.Logger {
}
if m != nil {
if err := logger.SetConfigWithMap(m); err != nil {
glog.Panic(err)
panic(err)
}
}
}
@ -172,15 +175,15 @@ func Database(name ...string) gdb.DB {
if gdb.GetConfig(group) != nil {
db, err := gdb.Instance(group)
if err != nil {
glog.Panic(err)
panic(err)
}
return db
}
m := config.GetMap("database")
if m == nil {
glog.Panic(`database init failed: "database" node not found, is config file or configuration missing?`)
panic(`database init failed: "database" node not found, is config file or configuration missing?`)
}
// Parse <m> as map-slice.
// Parse <m> as map-slice and adds it to gdb's global configurations.
for group, groupConfig := range m {
cg := gdb.ConfigGroup{}
switch value := groupConfig.(type) {
@ -199,14 +202,15 @@ func Database(name ...string) gdb.DB {
gdb.SetConfigGroup(group, cg)
}
}
// Parse <m> as a single node configuration.
// Parse <m> as a single node configuration,
// which is the default group configuration.
if node := parseDBConfigNode(m); node != nil {
cg := gdb.ConfigGroup{}
if node.LinkInfo != "" || node.Host != "" {
cg = append(cg, *node)
}
if len(cg) > 0 {
gdb.SetConfigGroup(group, cg)
gdb.SetConfigGroup(gdb.DEFAULT_GROUP_NAME, cg)
}
}
addConfigMonitor(instanceKey, config)
@ -219,12 +223,12 @@ func Database(name ...string) gdb.DB {
}
if m != nil {
if err := db.GetLogger().SetConfigWithMap(m); err != nil {
glog.Panic(err)
panic(err)
}
}
return db
} else {
glog.Panic(err)
panic(err)
}
return nil
})
@ -242,7 +246,7 @@ func parseDBConfigNode(value interface{}) *gdb.ConfigNode {
node := &gdb.ConfigNode{}
err := gconv.Struct(nodeMap, node)
if err != nil {
glog.Panic(err)
panic(err)
}
if _, v := gutil.MapPossibleItemByKey(nodeMap, "link"); v != nil {
node.LinkInfo = gconv.String(v)
@ -282,15 +286,15 @@ func Redis(name ...string) *gredis.Redis {
if v, ok := m[group]; ok {
redisConfig, err := gredis.ConfigFromStr(gconv.String(v))
if err != nil {
glog.Panic(err)
panic(err)
}
addConfigMonitor(instanceKey, config)
return gredis.New(redisConfig)
} else {
glog.Panicf(`configuration for redis not found for group "%s"`, group)
panic(fmt.Sprintf(`configuration for redis not found for group "%s"`, group))
}
} else {
glog.Panicf(`incomplete configuration for redis: "redis" node not found in config file "%s"`, config.FilePath())
panic(fmt.Sprintf(`incomplete configuration for redis: "redis" node not found in config file "%s"`, config.FilePath()))
}
return nil
})

View File

@ -8,5 +8,7 @@
package ghttp
var (
// paramTagPriority is the priority tag array for request parameter
// to struct field mapping.
paramTagPriority = []string{"param", "params", "p"}
)

View File

@ -6,122 +6,182 @@
package ghttp
// Get is a convenience method for sending GET request.
// NOTE that remembers CLOSING the response object when it'll never be used.
func Get(url string) (*ClientResponse, error) {
return DoRequest("GET", url)
}
// Put is a convenience method for sending PUT request.
// NOTE that remembers CLOSING the response object when it'll never be used.
func Put(url string, data ...interface{}) (*ClientResponse, error) {
return DoRequest("PUT", url, data...)
}
// Post is a convenience method for sending POST request.
// NOTE that remembers CLOSING the response object when it'll never be used.
func Post(url string, data ...interface{}) (*ClientResponse, error) {
return DoRequest("POST", url, data...)
}
// Delete is a convenience method for sending DELETE request.
// NOTE that remembers CLOSING the response object when it'll never be used.
func Delete(url string, data ...interface{}) (*ClientResponse, error) {
return DoRequest("DELETE", url, data...)
}
// Head is a convenience method for sending HEAD request.
// NOTE that remembers CLOSING the response object when it'll never be used.
func Head(url string, data ...interface{}) (*ClientResponse, error) {
return DoRequest("HEAD", url, data...)
}
// Patch is a convenience method for sending PATCH request.
// NOTE that remembers CLOSING the response object when it'll never be used.
func Patch(url string, data ...interface{}) (*ClientResponse, error) {
return DoRequest("PATCH", url, data...)
}
// Connect is a convenience method for sending CONNECT request.
// NOTE that remembers CLOSING the response object when it'll never be used.
func Connect(url string, data ...interface{}) (*ClientResponse, error) {
return DoRequest("CONNECT", url, data...)
}
// Options is a convenience method for sending OPTIONS request.
// NOTE that remembers CLOSING the response object when it'll never be used.
func Options(url string, data ...interface{}) (*ClientResponse, error) {
return DoRequest("OPTIONS", url, data...)
}
// Trace is a convenience method for sending TRACE request.
// NOTE that remembers CLOSING the response object when it'll never be used.
func Trace(url string, data ...interface{}) (*ClientResponse, error) {
return DoRequest("TRACE", url, data...)
}
// DoRequest is a convenience method for sending custom http method request.
// NOTE that remembers CLOSING the response object when it'll never be used.
func DoRequest(method, url string, data ...interface{}) (*ClientResponse, error) {
return NewClient().DoRequest(method, url, data...)
}
// GetContent is a convenience method for sending GET request, which retrieves and returns
// the result content and automatically closes response object.
func GetContent(url string, data ...interface{}) string {
return RequestContent("GET", url, data...)
}
// PutContent is a convenience method for sending PUT request, which retrieves and returns
// the result content and automatically closes response object.
func PutContent(url string, data ...interface{}) string {
return RequestContent("PUT", url, data...)
}
// PostContent is a convenience method for sending POST request, which retrieves and returns
// the result content and automatically closes response object.
func PostContent(url string, data ...interface{}) string {
return RequestContent("POST", url, data...)
}
// DeleteContent is a convenience method for sending DELETE request, which retrieves and returns
// the result content and automatically closes response object.
func DeleteContent(url string, data ...interface{}) string {
return RequestContent("DELETE", url, data...)
}
// HeadContent is a convenience method for sending HEAD request, which retrieves and returns
// the result content and automatically closes response object.
func HeadContent(url string, data ...interface{}) string {
return RequestContent("HEAD", url, data...)
}
// PatchContent is a convenience method for sending PATCH request, which retrieves and returns
// the result content and automatically closes response object.
func PatchContent(url string, data ...interface{}) string {
return RequestContent("PATCH", url, data...)
}
// ConnectContent is a convenience method for sending CONNECT request, which retrieves and returns
// the result content and automatically closes response object.
func ConnectContent(url string, data ...interface{}) string {
return RequestContent("CONNECT", url, data...)
}
// OptionsContent is a convenience method for sending OPTIONS request, which retrieves and returns
// the result content and automatically closes response object.
func OptionsContent(url string, data ...interface{}) string {
return RequestContent("OPTIONS", url, data...)
}
// TraceContent is a convenience method for sending TRACE request, which retrieves and returns
// the result content and automatically closes response object.
func TraceContent(url string, data ...interface{}) string {
return RequestContent("TRACE", url, data...)
}
// RequestContent is a convenience method for sending custom http method request, which
// retrieves and returns the result content and automatically closes response object.
func RequestContent(method string, url string, data ...interface{}) string {
return NewClient().RequestContent(method, url, data...)
}
// GetBytes is a convenience method for sending GET request, which retrieves and returns
// the result content as bytes and automatically closes response object.
func GetBytes(url string, data ...interface{}) []byte {
return RequestBytes("GET", url, data...)
}
// PutBytes is a convenience method for sending PUT request, which retrieves and returns
// the result content as bytes and automatically closes response object.
func PutBytes(url string, data ...interface{}) []byte {
return RequestBytes("PUT", url, data...)
}
// PostBytes is a convenience method for sending POST request, which retrieves and returns
// the result content as bytes and automatically closes response object.
func PostBytes(url string, data ...interface{}) []byte {
return RequestBytes("POST", url, data...)
}
// DeleteBytes is a convenience method for sending DELETE request, which retrieves and returns
// the result content as bytes and automatically closes response object.
func DeleteBytes(url string, data ...interface{}) []byte {
return RequestBytes("DELETE", url, data...)
}
// HeadBytes is a convenience method for sending HEAD request, which retrieves and returns
// the result content as bytes and automatically closes response object.
func HeadBytes(url string, data ...interface{}) []byte {
return RequestBytes("HEAD", url, data...)
}
// PatchBytes is a convenience method for sending PATCH request, which retrieves and returns
// the result content as bytes and automatically closes response object.
func PatchBytes(url string, data ...interface{}) []byte {
return RequestBytes("PATCH", url, data...)
}
// ConnectBytes is a convenience method for sending CONNECT request, which retrieves and returns
// the result content as bytes and automatically closes response object.
func ConnectBytes(url string, data ...interface{}) []byte {
return RequestBytes("CONNECT", url, data...)
}
// OptionsBytes is a convenience method for sending OPTIONS request, which retrieves and returns
// the result content as bytes and automatically closes response object.
func OptionsBytes(url string, data ...interface{}) []byte {
return RequestBytes("OPTIONS", url, data...)
}
// TraceBytes is a convenience method for sending TRACE request, which retrieves and returns
// the result content as bytes and automatically closes response object.
func TraceBytes(url string, data ...interface{}) []byte {
return RequestBytes("TRACE", url, data...)
}
// RequestBytes is a convenience method for sending custom http method request, which
// retrieves and returns the result content as bytes and automatically closes response object.
func RequestBytes(method string, url string, data ...interface{}) []byte {
return NewClient().RequestBytes(method, url, data...)
}

View File

@ -6,44 +6,53 @@
package ghttp
// GetBytes sends a GET request, retrieves and returns the result content as bytes.
func (c *Client) GetBytes(url string, data ...interface{}) []byte {
return c.RequestBytes("GET", url, data...)
}
// PutBytes sends a PUT request, retrieves and returns the result content as bytes.
func (c *Client) PutBytes(url string, data ...interface{}) []byte {
return c.RequestBytes("PUT", url, data...)
}
// PostBytes sends a POST request, retrieves and returns the result content as bytes.
func (c *Client) PostBytes(url string, data ...interface{}) []byte {
return c.RequestBytes("POST", url, data...)
}
// DeleteBytes sends a DELETE request, retrieves and returns the result content as bytes.
func (c *Client) DeleteBytes(url string, data ...interface{}) []byte {
return c.RequestBytes("DELETE", url, data...)
}
// HeadBytes sends a HEAD request, retrieves and returns the result content as bytes.
func (c *Client) HeadBytes(url string, data ...interface{}) []byte {
return c.RequestBytes("HEAD", url, data...)
}
// PatchBytes sends a PATCH request, retrieves and returns the result content as bytes.
func (c *Client) PatchBytes(url string, data ...interface{}) []byte {
return c.RequestBytes("PATCH", url, data...)
}
// ConnectBytes sends a CONNECT request, retrieves and returns the result content as bytes.
func (c *Client) ConnectBytes(url string, data ...interface{}) []byte {
return c.RequestBytes("CONNECT", url, data...)
}
// OptionsBytes sends a OPTIONS request, retrieves and returns the result content as bytes.
func (c *Client) OptionsBytes(url string, data ...interface{}) []byte {
return c.RequestBytes("OPTIONS", url, data...)
}
// TraceBytes sends a TRACE request, retrieves and returns the result content as bytes.
func (c *Client) TraceBytes(url string, data ...interface{}) []byte {
return c.RequestBytes("TRACE", url, data...)
}
// RequestBytes sends request using given HTTP method and data and returns the binary as bytes.
// It reads and closes the response object internally automatically.
// RequestBytes sends request using given HTTP method and data, retrieves returns the result
// as bytes. It reads and closes the response object internally automatically.
func (c *Client) RequestBytes(method string, url string, data ...interface{}) []byte {
response, err := c.DoRequest(method, url, data...)
if err != nil {

View File

@ -128,8 +128,15 @@ func (r *Request) GetMapStrStr(def ...map[string]interface{}) map[string]string
return r.GetRequestMapStrStr(def...)
}
// GetStruct is alias of GetRequestToStruct.
// See GetRequestToStruct.
func (r *Request) GetStruct(pointer interface{}, mapping ...map[string]string) error {
return r.GetRequestToStruct(pointer, mapping...)
}
// GetToStruct is alias of GetRequestToStruct.
// See GetRequestToStruct.
// Deprecated.
func (r *Request) GetToStruct(pointer interface{}, mapping ...map[string]string) error {
return r.GetRequestToStruct(pointer, mapping...)
}

View File

@ -154,10 +154,10 @@ func (r *Request) GetFormMapStrVar(kvMap ...map[string]interface{}) map[string]*
return nil
}
// GetFormToStruct retrieves all form parameters passed from client and converts them to
// GetFormStruct retrieves all form parameters passed from client and converts them to
// given struct object. Note that the parameter <pointer> is a pointer to the struct object.
// The optional parameter <mapping> is used to specify the key to attribute mapping.
func (r *Request) GetFormToStruct(pointer interface{}, mapping ...map[string]string) error {
func (r *Request) GetFormStruct(pointer interface{}, mapping ...map[string]string) error {
r.ParseForm()
tagMap := structs.TagMapName(pointer, paramTagPriority, true)
if len(mapping) > 0 {
@ -167,3 +167,9 @@ func (r *Request) GetFormToStruct(pointer interface{}, mapping ...map[string]str
}
return gconv.StructDeep(r.formMap, pointer, tagMap)
}
// GetFormToStruct is alias of GetFormStruct. See GetFormStruct.
// Deprecated.
func (r *Request) GetFormToStruct(pointer interface{}, mapping ...map[string]string) error {
return r.GetFormStruct(pointer, mapping...)
}

View File

@ -174,11 +174,11 @@ func (r *Request) GetPostMapStrVar(kvMap ...map[string]interface{}) map[string]*
return nil
}
// GetPostToStruct retrieves all parameters in the form and body passed from client
// GetPostStruct retrieves all parameters in the form and body passed from client
// and converts them to given struct object. Note that the parameter <pointer> is a pointer
// to the struct object. The optional parameter <mapping> is used to specify the key to
// attribute mapping.
func (r *Request) GetPostToStruct(pointer interface{}, mapping ...map[string]string) error {
func (r *Request) GetPostStruct(pointer interface{}, mapping ...map[string]string) error {
tagMap := structs.TagMapName(pointer, paramTagPriority, true)
if len(mapping) > 0 {
for k, v := range mapping[0] {
@ -187,3 +187,9 @@ func (r *Request) GetPostToStruct(pointer interface{}, mapping ...map[string]str
}
return gconv.StructDeep(r.GetPostMap(), pointer, tagMap)
}
// GetPostToStruct is alias of GetQueryStruct. See GetPostStruct.
// Deprecated.
func (r *Request) GetPostToStruct(pointer interface{}, mapping ...map[string]string) error {
return r.GetPostStruct(pointer, mapping...)
}

View File

@ -188,11 +188,11 @@ func (r *Request) GetQueryMapStrVar(kvMap ...map[string]interface{}) map[string]
return nil
}
// GetQueryToStruct retrieves all parameters passed from client using HTTP GET method
// GetQueryStruct retrieves all parameters passed from client using HTTP GET method
// and converts them to given struct object. Note that the parameter <pointer> is a pointer
// to the struct object. The optional parameter <mapping> is used to specify the key to
// attribute mapping.
func (r *Request) GetQueryToStruct(pointer interface{}, mapping ...map[string]string) error {
func (r *Request) GetQueryStruct(pointer interface{}, mapping ...map[string]string) error {
r.ParseQuery()
tagMap := structs.TagMapName(pointer, paramTagPriority, true)
if len(mapping) > 0 {
@ -202,3 +202,9 @@ func (r *Request) GetQueryToStruct(pointer interface{}, mapping ...map[string]st
}
return gconv.StructDeep(r.GetQueryMap(), pointer, tagMap)
}
// GetQueryToStruct is alias of GetQueryStruct. See GetQueryStruct.
// Deprecated.
func (r *Request) GetQueryToStruct(pointer interface{}, mapping ...map[string]string) error {
return r.GetQueryStruct(pointer, mapping...)
}

View File

@ -263,10 +263,10 @@ func (r *Request) GetRequestMapStrVar(kvMap ...map[string]interface{}) map[strin
return nil
}
// GetRequestToStruct retrieves all parameters passed from client no matter what HTTP method the client is using,
// GetRequestStruct retrieves all parameters passed from client no matter what HTTP method the client is using,
// and converts them to given struct object. Note that the parameter <pointer> is a pointer to the struct object.
// The optional parameter <mapping> is used to specify the key to attribute mapping.
func (r *Request) GetRequestToStruct(pointer interface{}, mapping ...map[string]string) error {
func (r *Request) GetRequestStruct(pointer interface{}, mapping ...map[string]string) error {
tagMap := structs.TagMapName(pointer, paramTagPriority, true)
if len(mapping) > 0 {
for k, v := range mapping[0] {
@ -275,3 +275,9 @@ func (r *Request) GetRequestToStruct(pointer interface{}, mapping ...map[string]
}
return gconv.StructDeep(r.GetRequestMap(), pointer, tagMap)
}
// GetRequestToStruct is alias of GetRequestStruct. See GetRequestStruct.
// Deprecated.
func (r *Request) GetRequestToStruct(pointer interface{}, mapping ...map[string]string) error {
return r.GetRequestStruct(pointer, mapping...)
}

View File

@ -335,31 +335,20 @@ func (s *Server) dumpRouterMap() {
if s.config.DumpRouterMap && len(s.routesMap) > 0 {
buffer := bytes.NewBuffer(nil)
table := tablewriter.NewWriter(buffer)
table.SetHeader([]string{"SERVER", "ADDRESS", "DOMAIN", "METHOD", "P", "ROUTE", "HANDLER", "MIDDLEWARE"})
table.SetHeader([]string{"SERVER", "DOMAIN", "ADDRESS", "METHOD", "ROUTE", "HANDLER", "MIDDLEWARE"})
table.SetRowLine(true)
table.SetBorder(false)
table.SetCenterSeparator("|")
table.SetColumnAlignment([]int{
tablewriter.ALIGN_CENTER,
tablewriter.ALIGN_CENTER,
tablewriter.ALIGN_CENTER,
tablewriter.ALIGN_CENTER,
tablewriter.ALIGN_CENTER,
tablewriter.ALIGN_LEFT,
tablewriter.ALIGN_LEFT,
tablewriter.ALIGN_LEFT,
})
for _, item := range s.GetRouterArray() {
data := make([]string, 8)
data := make([]string, 7)
data[0] = item.Server
data[1] = item.Address
data[2] = item.Domain
data[1] = item.Domain
data[2] = item.Address
data[3] = item.Method
data[4] = gconv.String(len(strings.Split(item.Route, "/")) - 1 + item.Priority)
data[5] = item.Route
data[6] = item.handler.itemName
data[7] = item.Middleware
data[4] = item.Route
data[5] = item.handler.itemName
data[6] = item.Middleware
table.Append(data)
}
table.Render()

View File

@ -63,7 +63,7 @@ func receiveTcpListening() {
}
// Save the port to the pid file.
if err := gfile.PutContents(getCommFilePath(Pid()), gconv.String(i)); err != nil {
glog.Panic(err)
panic(err)
}
break
}

View File

@ -8,6 +8,7 @@ package gsession
import (
"encoding/json"
"fmt"
"github.com/gogf/gf/container/gmap"
"github.com/gogf/gf/internal/intlog"
"os"
@ -22,8 +23,6 @@ import (
"github.com/gogf/gf/os/gtime"
"github.com/gogf/gf/os/glog"
"github.com/gogf/gf/os/gfile"
)
@ -39,7 +38,7 @@ var (
DefaultStorageFilePath = gfile.Join(gfile.TempDir(), "gsessions")
DefaultStorageFileCryptoKey = []byte("Session storage file crypto key!")
DefaultStorageFileCryptoEnabled = false
DefaultStorageFileLoopInterval = time.Minute
DefaultStorageFileLoopInterval = 10 * time.Second
)
func init() {
@ -55,15 +54,15 @@ func NewStorageFile(path ...string) *StorageFile {
if len(path) > 0 && path[0] != "" {
storagePath, _ = gfile.Search(path[0])
if storagePath == "" {
glog.Panicf("'%s' does not exist", path[0])
panic(fmt.Sprintf(fmt.Sprintf("'%s' does not exist", path[0])))
}
if !gfile.IsWritable(storagePath) {
glog.Panicf("'%s' is not writable", path[0])
panic(fmt.Sprintf("'%s' is not writable", path[0]))
}
}
if storagePath != "" {
if err := gfile.Mkdir(storagePath); err != nil {
glog.Panicf("mkdir '%s' failed: %v", path[0], err)
panic(fmt.Sprintf("mkdir '%s' failed: %v", path[0], err))
}
}
s := &StorageFile{

View File

@ -53,8 +53,9 @@ func TrimLeft(str string, characterMask ...string) string {
// TrimLeftStr strips all of the given <cut> string from the beginning of a string.
// Note that it does not strips the whitespaces of its beginning.
func TrimLeftStr(str string, cut string) string {
for str[0:len(cut)] == cut {
str = str[len(cut):]
var lenCut = len(cut)
for len(str) >= lenCut && str[0:lenCut] == cut {
str = str[lenCut:]
}
return str
}
@ -71,14 +72,12 @@ func TrimRight(str string, characterMask ...string) string {
// TrimRightStr strips all of the given <cut> string from the end of a string.
// Note that it does not strips the whitespaces of its end.
func TrimRightStr(str string, cut string) string {
var length int
for {
length = len(str)
if str[length-len(cut):length] == cut {
str = str[:length-len(cut)]
} else {
break
}
var lenStr = len(str)
var lenCut = len(cut)
for lenStr >= lenCut && str[lenStr-lenCut:lenStr] == cut {
lenStr = lenStr - lenCut
str = str[:lenStr]
}
return str
}

View File

@ -41,9 +41,11 @@ func Test_TrimRight(t *testing.T) {
func Test_TrimRightStr(t *testing.T) {
gtest.Case(t, func() {
gtest.Assert(gstr.TrimRightStr("gogo我爱gogo", "go"), "gogo我爱")
gtest.Assert(gstr.TrimRightStr("gogo我爱gogo", "go我爱gogo"), "go")
})
gtest.Case(t, func() {
gtest.Assert(gstr.TrimRightStr("我爱中国人", "人"), "我爱中国")
gtest.Assert(gstr.TrimRightStr("我爱中国人", "爱中国人"), "我")
})
}
@ -57,8 +59,10 @@ func Test_TrimLeft(t *testing.T) {
func Test_TrimLeftStr(t *testing.T) {
gtest.Case(t, func() {
gtest.Assert(gstr.TrimLeftStr("gogo我爱gogo", "go"), "我爱gogo")
gtest.Assert(gstr.TrimLeftStr("gogo我爱gogo", "gogo我爱go"), "go")
})
gtest.Case(t, func() {
gtest.Assert(gstr.TrimLeftStr("我爱中国人", "我爱"), "中国人")
gtest.Assert(gstr.TrimLeftStr("我爱中国人", "我爱中国"), "人")
})
}