diff --git a/README.md b/README.md index e366a634..797df536 100644 --- a/README.md +++ b/README.md @@ -6,10 +6,6 @@ Xorm is a simple and powerful ORM for Go. [![](https://goreportcard.com/badge/github.com/go-xorm/xorm)](https://goreportcard.com/report/github.com/go-xorm/xorm) [![Join the chat at https://img.shields.io/discord/323460943201959939.svg](https://img.shields.io/discord/323460943201959939.svg)](https://discord.gg/HuR2CF3) -# Notice - -The last master version is not backwards compatible. You should use `engine.ShowSQL()` and `engine.Logger().SetLevel()` instead of `engine.ShowSQL = `, `engine.ShowInfo = ` and so on. - # Features * Struct <-> Table Mapping Support @@ -52,6 +48,14 @@ Drivers for Go's sql package which currently support database/sql includes: # Changelog +* **v0.6.3** + * merge tests to main project + * add `Exist` function + * add `SumInt` function + * Mysql now support read and create column comment. + * fix time related bugs. + * fix some other bugs. + * **v0.6.2** * refactor tag parse methods * add Scan features to Get @@ -68,18 +72,6 @@ methods can use `builder.Cond` as parameter * logging interface changed * some bugs fixed -* **v0.4.5** - * many bugs fixed - * extends support unlimited deepth - * Delete Limit support - -* **v0.4.4** - * ql database expriment support - * tidb database expriment support - * sql.NullString and etc. field support - * select ForUpdate support - * many bugs fixed - [More changes ...](https://github.com/go-xorm/manual-en-US/tree/master/chapter-16) # Installation @@ -168,6 +160,25 @@ has, err := engine.Where("id = ?", id).Cols(cols...).Get(&valuesSlice) // SELECT col1, col2, col3 FROM user WHERE id = ? ``` +* Check if one record exist on table + +```Go +has, err := testEngine.Exist(new(RecordExist)) +// SELECT * FROM record_exist LIMIT 1 +has, err = testEngine.Exist(&RecordExist{ + Name: "test1", + }) +// SELECT * FROM record_exist WHERE name = ? LIMIT 1 +has, err = testEngine.Where("name = ?", "test1").Exist(&RecordExist{}) +// SELECT * FROM record_exist WHERE name = ? LIMIT 1 +has, err = testEngine.SQL("select * from record_exist where name = ?", "test1").Exist() +// select * from record_exist where name = ? +has, err = testEngine.Table("record_exist").Exist() +// SELECT * FROM record_exist LIMIT 1 +has, err = testEngine.Table("record_exist").Where("name = ?", "test1").Exist() +// SELECT * FROM record_exist WHERE name = ? LIMIT 1 +``` + * Query multiple records from database, also you can use join and extends ```Go @@ -260,6 +271,12 @@ err := engine.Where(builder.NotIn("a", 1, 2).And(builder.In("b", "c", "d", "e")) # Cases +* [Gitea](http://gitea.io) - [github.com/go-gitea/gitea](http://github.com/go-gitea/gitea) + +* [Gogs](http://try.gogits.org) - [github.com/gogits/gogs](http://github.com/gogits/gogs) + +* [grafana](https://grafana.com/) - [github.com/grafana/grafana](http://github.com/grafana/grafana) + * [github.com/m3ng9i/qreader](https://github.com/m3ng9i/qreader) * [Wego](http://github.com/go-tango/wego) @@ -268,8 +285,6 @@ err := engine.Where(builder.NotIn("a", 1, 2).And(builder.In("b", "c", "d", "e")) * [Xorm Adapter](https://github.com/casbin/xorm-adapter) for [Casbin](https://github.com/casbin/casbin) - [github.com/casbin/xorm-adapter](https://github.com/casbin/xorm-adapter) -* [Gogs](http://try.gogits.org) - [github.com/gogits/gogs](http://github.com/gogits/gogs) - * [Gorevel](http://gorevel.cn/) - [github.com/goofcc/gorevel](http://github.com/goofcc/gorevel) * [Gowalker](http://gowalker.org) - [github.com/Unknwon/gowalker](http://github.com/Unknwon/gowalker) diff --git a/README_CN.md b/README_CN.md index 66a3c015..53cc50af 100644 --- a/README_CN.md +++ b/README_CN.md @@ -8,10 +8,6 @@ xorm是一个简单而强大的Go语言ORM库. 通过它可以使数据库操作 [![](https://goreportcard.com/badge/github.com/go-xorm/xorm)](https://goreportcard.com/report/github.com/go-xorm/xorm) [![Join the chat at https://img.shields.io/discord/323460943201959939.svg](https://img.shields.io/discord/323460943201959939.svg)](https://discord.gg/HuR2CF3) -# 注意 - -最新的版本有不兼容的更新,您必须使用 `engine.ShowSQL()` 和 `engine.Logger().SetLevel()` 来替代 `engine.ShowSQL = `, `engine.ShowInfo = ` 等等。 - ## 特性 * 支持Struct和数据库表之间的灵活映射,并支持自动同步 @@ -56,6 +52,15 @@ xorm是一个简单而强大的Go语言ORM库. 通过它可以使数据库操作 ## 更新日志 +* **v0.6.3** + * 合并单元测试到主工程 + * 新增`Exist`方法 + * 新增`SumInt`方法 + * Mysql新增读取和创建字段注释支持 + * 新增`SetConnMaxLifetime`方法 + * 修正了时间相关的Bug + * 修复了一些其它Bug + * **v0.6.2** * 重构Tag解析方式 * Get方法新增类似Scan的特性 @@ -72,18 +77,6 @@ xorm是一个简单而强大的Go语言ORM库. 通过它可以使数据库操作 * logging接口进行不兼容改变 * Bug修正 -* **v0.4.5** - * bug修正 - * extends 支持无限级 - * Delete Limit 支持 - -* **v0.4.4** - * Tidb 数据库支持 - * QL 试验性支持 - * sql.NullString支持 - * ForUpdate 支持 - * bug修正 - [更多更新日志...](https://github.com/go-xorm/manual-zh-CN/tree/master/chapter-16) ## 安装 @@ -172,6 +165,25 @@ has, err := engine.Where("id = ?", id).Cols(cols...).Get(&valuesSlice) // SELECT col1, col2, col3 FROM user WHERE id = ? ``` +* 检测记录是否存在 + +```Go +has, err := testEngine.Exist(new(RecordExist)) +// SELECT * FROM record_exist LIMIT 1 +has, err = testEngine.Exist(&RecordExist{ + Name: "test1", + }) +// SELECT * FROM record_exist WHERE name = ? LIMIT 1 +has, err = testEngine.Where("name = ?", "test1").Exist(&RecordExist{}) +// SELECT * FROM record_exist WHERE name = ? LIMIT 1 +has, err = testEngine.SQL("select * from record_exist where name = ?", "test1").Exist() +// select * from record_exist where name = ? +has, err = testEngine.Table("record_exist").Exist() +// SELECT * FROM record_exist LIMIT 1 +has, err = testEngine.Table("record_exist").Where("name = ?", "test1").Exist() +// SELECT * FROM record_exist WHERE name = ? LIMIT 1 +``` + * 查询多条记录,当然可以使用Join和extends来组合使用 ```Go @@ -263,6 +275,12 @@ err := engine.Where(builder.NotIn("a", 1, 2).And(builder.In("b", "c", "d", "e")) # 案例 +* [Gitea](http://gitea.io) - [github.com/go-gitea/gitea](http://github.com/go-gitea/gitea) + +* [Gogs](http://try.gogits.org) - [github.com/gogits/gogs](http://github.com/gogits/gogs) + +* [grafana](https://grafana.com/) - [github.com/grafana/grafana](http://github.com/grafana/grafana) + * [github.com/m3ng9i/qreader](https://github.com/m3ng9i/qreader) * [Wego](http://github.com/go-tango/wego) @@ -271,8 +289,6 @@ err := engine.Where(builder.NotIn("a", 1, 2).And(builder.In("b", "c", "d", "e")) * [Xorm Adapter](https://github.com/casbin/xorm-adapter) for [Casbin](https://github.com/casbin/casbin) - [github.com/casbin/xorm-adapter](https://github.com/casbin/xorm-adapter) -* [Gogs](http://try.gogits.org) - [github.com/gogits/gogs](http://github.com/gogits/gogs) - * [Gowalker](http://gowalker.org) - [github.com/Unknwon/gowalker](http://github.com/Unknwon/gowalker) * [Gobuild.io](http://gobuild.io) - [github.com/shxsun/gobuild](http://github.com/shxsun/gobuild) diff --git a/engine.go b/engine.go index 5c48710e..84e9206d 100644 --- a/engine.go +++ b/engine.go @@ -1426,6 +1426,13 @@ func (engine *Engine) Get(bean interface{}) (bool, error) { return session.Get(bean) } +// Exist returns true if the record exist otherwise return false +func (engine *Engine) Exist(bean ...interface{}) (bool, error) { + session := engine.NewSession() + defer session.Close() + return session.Exist(bean...) +} + // Find retrieve records from table, condiBeans's non-empty fields // are conditions. beans could be []Struct, []*Struct, map[int64]Struct // map[int64]*Struct diff --git a/session_exist.go b/session_exist.go new file mode 100644 index 00000000..6f895c1e --- /dev/null +++ b/session_exist.go @@ -0,0 +1,87 @@ +// Copyright 2017 The Xorm Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package xorm + +import ( + "errors" + "fmt" + "reflect" + + "github.com/go-xorm/builder" + "github.com/go-xorm/core" +) + +// Exist returns true if the record exist otherwise return false +func (session *Session) Exist(bean ...interface{}) (bool, error) { + defer session.resetStatement() + if session.IsAutoClose { + defer session.Close() + } + + var sqlStr string + var args []interface{} + var err error + + if session.Statement.RawSQL == "" { + if len(bean) == 0 { + tableName := session.Statement.TableName() + if len(tableName) <= 0 { + return false, ErrTableNotFound + } + + if session.Statement.cond.IsValid() { + condSQL, condArgs, err := builder.ToSQL(session.Statement.cond) + if err != nil { + return false, err + } + + sqlStr = fmt.Sprintf("SELECT * FROM %s WHERE %s LIMIT 1", tableName, condSQL) + args = condArgs + } else { + sqlStr = fmt.Sprintf("SELECT * FROM %s LIMIT 1", tableName) + args = []interface{}{} + } + } else { + beanValue := reflect.ValueOf(bean[0]) + if beanValue.Kind() != reflect.Ptr { + return false, errors.New("needs a pointer") + } + + if beanValue.Elem().Kind() == reflect.Struct { + if err := session.Statement.setRefValue(beanValue.Elem()); err != nil { + return false, err + } + } + + if len(session.Statement.TableName()) <= 0 { + return false, ErrTableNotFound + } + session.Statement.Limit(1) + sqlStr, args, err = session.Statement.genGetSQL(bean[0]) + if err != nil { + return false, err + } + } + } else { + sqlStr = session.Statement.RawSQL + args = session.Statement.RawParams + } + + session.queryPreprocess(&sqlStr, args...) + + var rawRows *core.Rows + if session.IsAutoCommit { + _, rawRows, err = session.innerQuery(sqlStr, args...) + } else { + rawRows, err = session.Tx.Query(sqlStr, args...) + } + if err != nil { + return false, err + } + + defer rawRows.Close() + + return rawRows.Next(), nil +} diff --git a/session_exist_test.go b/session_exist_test.go new file mode 100644 index 00000000..857bf4a1 --- /dev/null +++ b/session_exist_test.go @@ -0,0 +1,76 @@ +// Copyright 2017 The Xorm Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package xorm + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestExistStruct(t *testing.T) { + assert.NoError(t, prepareEngine()) + + type RecordExist struct { + Id int64 + Name string + } + + assertSync(t, new(RecordExist)) + + has, err := testEngine.Exist(new(RecordExist)) + assert.NoError(t, err) + assert.False(t, has) + + cnt, err := testEngine.Insert(&RecordExist{ + Name: "test1", + }) + assert.NoError(t, err) + assert.EqualValues(t, 1, cnt) + + has, err = testEngine.Exist(new(RecordExist)) + assert.NoError(t, err) + assert.True(t, has) + + has, err = testEngine.Exist(&RecordExist{ + Name: "test1", + }) + assert.NoError(t, err) + assert.True(t, has) + + has, err = testEngine.Exist(&RecordExist{ + Name: "test2", + }) + assert.NoError(t, err) + assert.False(t, has) + + has, err = testEngine.Where("name = ?", "test1").Exist(&RecordExist{}) + assert.NoError(t, err) + assert.True(t, has) + + has, err = testEngine.Where("name = ?", "test2").Exist(&RecordExist{}) + assert.NoError(t, err) + assert.False(t, has) + + has, err = testEngine.SQL("select * from record_exist where name = ?", "test1").Exist() + assert.NoError(t, err) + assert.True(t, has) + + has, err = testEngine.SQL("select * from record_exist where name = ?", "test2").Exist() + assert.NoError(t, err) + assert.False(t, has) + + has, err = testEngine.Table("record_exist").Exist() + assert.NoError(t, err) + assert.True(t, has) + + has, err = testEngine.Table("record_exist").Where("name = ?", "test1").Exist() + assert.NoError(t, err) + assert.True(t, has) + + has, err = testEngine.Table("record_exist").Where("name = ?", "test2").Exist() + assert.NoError(t, err) + assert.False(t, has) +} diff --git a/xorm.go b/xorm.go index 8b2fd6c6..36895a9d 100644 --- a/xorm.go +++ b/xorm.go @@ -17,7 +17,7 @@ import ( const ( // Version show the xorm's version - Version string = "0.6.2.0605" + Version string = "0.6.3.0713" ) func regDrvsNDialects() bool {