Lunny Xiao
062d9960b2
Merge branch 'master' into jcsalem/fix/nil_ptr_is_nullable fix bug when buffersize with iterate (#941) Merge branch 'master' into lunny/fix_buffer_iterate Exclude schema from index name (#1505) Merge branch 'master' into fix-schema-idx SetExpr support more go types (#1499) Improve tests SetExpr support more go types fix vet fix drone lint remove go1.10 test on drone Reviewed-on: xorm/xorm#1499 fix vet fix drone lint remove go1.10 test on drone Exclude schema from the index name Co-authored-by: Guillermo Prandi <guillep2k@users.noreply.github.com> Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com> Reviewed-on: xorm/xorm#1505 fix test fix bug fix bug when buffersize with iterate SetExpr support more go types (#1499) Improve tests SetExpr support more go types fix vet fix drone lint remove go1.10 test on drone Reviewed-on: xorm/xorm#1499 fix vet fix drone lint remove go1.10 test on drone Fix update with Alias (#1455) Co-authored-by: Guillermo Prandi <guillep2k@noreply.gitea.io> Reviewed-on: xorm/xorm#941 fix update map with version (#1448) fix test fix update map with version SetExpr support more go types (#1499) Improve tests SetExpr support more go types fix vet fix drone lint remove go1.10 test on drone Reviewed-on: xorm/xorm#1499 fix vet fix drone lint remove go1.10 test on drone Fix update with Alias (#1455) Reviewed-on: xorm/xorm#1448 Exclude schema from index name (#1505) Merge branch 'master' into fix-schema-idx SetExpr support more go types (#1499) Improve tests SetExpr support more go types fix vet fix drone lint remove go1.10 test on drone Reviewed-on: xorm/xorm#1499 fix vet fix drone lint remove go1.10 test on drone Exclude schema from the index name Co-authored-by: Guillermo Prandi <guillep2k@users.noreply.github.com> Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com> Reviewed-on: xorm/xorm#1505 SetExpr support more go types (#1499) Improve tests SetExpr support more go types fix vet fix drone lint remove go1.10 test on drone Reviewed-on: xorm/xorm#1499 For nullable columns, store nil values as NULL fix vet fix drone lint remove go1.10 test on drone Fix update with Alias (#1455) Improve ci tests (#1477) Rewrite Engine.QuoteTo() to accept multi-part identifiers (#1476) Support local sql log (#1338) Fix go mod and update version (#1460) Move github.com/go-xorm/xorm to xorm.io/xorm (#1459) add support custom type Nullfloat64 (#1450) fix bug when query map condtion with no quote (#1449) Don't warn when bool column default is 1 but not true (#1447) * don't warn when bool column default is 1 but not true * fix default case sensitive Fix sync2 with custom table name (#1445) * fix sync2 with custom table name * fix bug on postgres * fix bug on postgres fix bug when update with setexpr (#1446) add tidb tests on drone ci (#1444) improve sync2 (#1443) Fix wrong dbmetas (#1442) * add tests for db metas * add more tests * fix bug on mssql Fix default value parse bugs (#1437) * fix default value * fix default value tags * fix postgres default * fix default on postgres * fix default on postgres * fix mssql default fix arg conversion (#1441) * fix arg conversion * fix bugs * fix bug on postgres * use traditional positional parameters on insert into select * remove unnecessary tests upgrade core (#1440) add tests (#1439) add go1.13 tests on drone (#1416) Fix bug on insert where (#1436) * fix bug on insert where * fix bug * fix lint fix bug when insert multiple slices with customize table name (#1433) * fix bug when insert multiple slices with customize table name * fix tests on mssql * fix tests fix insert where with bool bug on mssql (#1432) fix setexpr missing big quotes (#1431) * fix setexpr missing big quotes * fix tests * fix tests Add support subquery on SetExpr (#1428) * add support subquery on SetExpr * fix tests fix go mod (#1427) fix tests (#1429) Use strings.Builder instead of builder.StringBuilder (#1417) * use strings.Builder instead of builder.StringBuilder * fix dependency * fix dependency Remove unuse get cols code (#1413) Add mssql ci test (#1410) * add mssql ci test * fix drone test Add insert select where support (#1401) Use drone new format (#1388) * use drone new format fix get customize type bug (#1382) fix bugs (#1375) update drone (#1374) Add tests for get var (#1305) * add test for SQL get * fix tests fix error when get null var (#890) * fix error when get null var * add support get for null var * fix bug Remove quotestr totally (#1366) * remove QuoteStr() totally * update xorm.core -> v0.7.0 * update dialect Quote remove QuoteStr() usage in dialects (#1364) document of FindAndCount() (#1365) remove QuoteStr() usage (#1360) make sure timeout in context timeout t... Co-authored-by: Guillermo Prandi <guillep2k@noreply.gitea.io> Co-authored-by: Jim Salem <jim@komand.com> Co-authored-by: Guillermo Prandi <guillep2k@noreply@gitea.io> Co-authored-by: yudppp <yu.d.ppp@gmail.com> Co-authored-by: BetaCat <outman99@hotmail.com> Reviewed-on: xorm/xorm#531 |
||
---|---|---|
.circleci | ||
docs/images | ||
examples | ||
migrate | ||
.drone.yml | ||
.gitignore | ||
cache_lru_test.go | ||
cache_lru.go | ||
cache_memory_store_test.go | ||
cache_memory_store.go | ||
cache_test.go | ||
context_cache.go | ||
CONTRIBUTING.md | ||
convert.go | ||
dialect_mssql_test.go | ||
dialect_mssql.go | ||
dialect_mysql.go | ||
dialect_oracle.go | ||
dialect_postgres_test.go | ||
dialect_postgres.go | ||
dialect_sqlite3_test.go | ||
dialect_sqlite3.go | ||
doc.go | ||
engine_cond.go | ||
engine_context_test.go | ||
engine_context.go | ||
engine_group_policy.go | ||
engine_group.go | ||
engine_table_test.go | ||
engine_table.go | ||
engine_test.go | ||
engine.go | ||
error.go | ||
gen_reserved.sh | ||
go.mod | ||
go.sum | ||
helpers_test.go | ||
helpers.go | ||
helpler_time.go | ||
interface.go | ||
json.go | ||
LICENSE | ||
logger.go | ||
pg_reserved.txt | ||
processors_test.go | ||
processors.go | ||
README_CN.md | ||
README.md | ||
rows_test.go | ||
rows.go | ||
session_cols_test.go | ||
session_cols.go | ||
session_cond_test.go | ||
session_cond.go | ||
session_context_test.go | ||
session_context.go | ||
session_convert.go | ||
session_delete_test.go | ||
session_delete.go | ||
session_exist_test.go | ||
session_exist.go | ||
session_find_test.go | ||
session_find.go | ||
session_get_test.go | ||
session_get.go | ||
session_insert_test.go | ||
session_insert.go | ||
session_iterate_test.go | ||
session_iterate.go | ||
session_pk_test.go | ||
session_query_test.go | ||
session_query.go | ||
session_raw_test.go | ||
session_raw.go | ||
session_schema_test.go | ||
session_schema.go | ||
session_stats_test.go | ||
session_stats.go | ||
session_test.go | ||
session_tx_test.go | ||
session_tx.go | ||
session_update_test.go | ||
session_update.go | ||
session.go | ||
statement_args.go | ||
statement_columnmap.go | ||
statement_exprparam.go | ||
statement_quote.go | ||
statement_test.go | ||
statement.go | ||
syslogger.go | ||
tag_cache_test.go | ||
tag_extends_test.go | ||
tag_id_test.go | ||
tag_test.go | ||
tag_version_test.go | ||
tag.go | ||
test_mssql_cache.sh | ||
test_mssql.sh | ||
test_mymysql_cache.sh | ||
test_mymysql.sh | ||
test_mysql_cache.sh | ||
test_mysql.sh | ||
test_postgres_cache.sh | ||
test_postgres.sh | ||
test_sqlite_cache.sh | ||
test_sqlite.sh | ||
test_tidb.sh | ||
time_test.go | ||
transaction.go | ||
transancation_test.go | ||
types_null_test.go | ||
types_test.go | ||
types.go | ||
xorm_test.go | ||
xorm.go |
xorm
Xorm is a simple and powerful ORM for Go.
Features
-
Struct <-> Table Mapping Support
-
Chainable APIs
-
Transaction Support
-
Both ORM and raw SQL operation Support
-
Sync database schema Support
-
Query Cache speed up
-
Database Reverse support, See Xorm Tool README
-
Simple cascade loading support
-
Optimistic Locking support
-
SQL Builder support via xorm.io/builder
-
Automatical Read/Write seperatelly
-
Postgres schema support
-
Context Cache support
Drivers Support
Drivers for Go's sql package which currently support database/sql includes:
-
MyMysql: github.com/ziutek/mymysql/godrv
-
Postgres: github.com/lib/pq
-
Tidb: github.com/pingcap/tidb
-
SQLite: github.com/mattn/go-sqlite3
-
Oracle: github.com/mattn/go-oci8 (experiment)
Installation
go get xorm.io/xorm
Documents
Quick Start
- Create Engine
engine, err := xorm.NewEngine(driverName, dataSourceName)
- Define a struct and Sync2 table struct to database
type User struct {
Id int64
Name string
Salt string
Age int
Passwd string `xorm:"varchar(200)"`
Created time.Time `xorm:"created"`
Updated time.Time `xorm:"updated"`
}
err := engine.Sync2(new(User))
- Create Engine Group
dataSourceNameSlice := []string{masterDataSourceName, slave1DataSourceName, slave2DataSourceName}
engineGroup, err := xorm.NewEngineGroup(driverName, dataSourceNameSlice)
masterEngine, err := xorm.NewEngine(driverName, masterDataSourceName)
slave1Engine, err := xorm.NewEngine(driverName, slave1DataSourceName)
slave2Engine, err := xorm.NewEngine(driverName, slave2DataSourceName)
engineGroup, err := xorm.NewEngineGroup(masterEngine, []*Engine{slave1Engine, slave2Engine})
Then all place where engine
you can just use engineGroup
.
Query
runs a SQL string, the returned results is[]map[string][]byte
,QueryString
returns[]map[string]string
,QueryInterface
returns[]map[string]interface{}
.
results, err := engine.Query("select * from user")
results, err := engine.Where("a = 1").Query()
results, err := engine.QueryString("select * from user")
results, err := engine.Where("a = 1").QueryString()
results, err := engine.QueryInterface("select * from user")
results, err := engine.Where("a = 1").QueryInterface()
Exec
runs a SQL string, it returnsaffected
anderror
affected, err := engine.Exec("update user set age = ? where name = ?", age, name)
Insert
one or multiple records to database
affected, err := engine.Insert(&user)
// INSERT INTO struct () values ()
affected, err := engine.Insert(&user1, &user2)
// INSERT INTO struct1 () values ()
// INSERT INTO struct2 () values ()
affected, err := engine.Insert(&users)
// INSERT INTO struct () values (),(),()
affected, err := engine.Insert(&user1, &users)
// INSERT INTO struct1 () values ()
// INSERT INTO struct2 () values (),(),()
Get
query one record from database
has, err := engine.Get(&user)
// SELECT * FROM user LIMIT 1
has, err := engine.Where("name = ?", name).Desc("id").Get(&user)
// SELECT * FROM user WHERE name = ? ORDER BY id DESC LIMIT 1
var name string
has, err := engine.Table(&user).Where("id = ?", id).Cols("name").Get(&name)
// SELECT name FROM user WHERE id = ?
var id int64
has, err := engine.Table(&user).Where("name = ?", name).Cols("id").Get(&id)
has, err := engine.SQL("select id from user").Get(&id)
// SELECT id FROM user WHERE name = ?
var valuesMap = make(map[string]string)
has, err := engine.Table(&user).Where("id = ?", id).Get(&valuesMap)
// SELECT * FROM user WHERE id = ?
var valuesSlice = make([]interface{}, len(cols))
has, err := engine.Table(&user).Where("id = ?", id).Cols(cols...).Get(&valuesSlice)
// SELECT col1, col2, col3 FROM user WHERE id = ?
Exist
check if one record exist on table
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
Find
query multiple records from database, also you can use join and extends
var users []User
err := engine.Where("name = ?", name).And("age > 10").Limit(10, 0).Find(&users)
// SELECT * FROM user WHERE name = ? AND age > 10 limit 10 offset 0
type Detail struct {
Id int64
UserId int64 `xorm:"index"`
}
type UserDetail struct {
User `xorm:"extends"`
Detail `xorm:"extends"`
}
var users []UserDetail
err := engine.Table("user").Select("user.*, detail.*").
Join("INNER", "detail", "detail.user_id = user.id").
Where("user.name = ?", name).Limit(10, 0).
Find(&users)
// SELECT user.*, detail.* FROM user INNER JOIN detail WHERE user.name = ? limit 10 offset 0
Iterate
andRows
query multiple records and record by record handle, there are two methods Iterate and Rows
err := engine.Iterate(&User{Name:name}, func(idx int, bean interface{}) error {
user := bean.(*User)
return nil
})
// SELECT * FROM user
err := engine.BufferSize(100).Iterate(&User{Name:name}, func(idx int, bean interface{}) error {
user := bean.(*User)
return nil
})
// SELECT * FROM user Limit 0, 100
// SELECT * FROM user Limit 101, 100
rows, err := engine.Rows(&User{Name:name})
// SELECT * FROM user
defer rows.Close()
bean := new(Struct)
for rows.Next() {
err = rows.Scan(bean)
}
Update
update one or more records, default will update non-empty and non-zero fields except when you use Cols, AllCols and so on.
affected, err := engine.ID(1).Update(&user)
// UPDATE user SET ... Where id = ?
affected, err := engine.Update(&user, &User{Name:name})
// UPDATE user SET ... Where name = ?
var ids = []int64{1, 2, 3}
affected, err := engine.In("id", ids).Update(&user)
// UPDATE user SET ... Where id IN (?, ?, ?)
// force update indicated columns by Cols
affected, err := engine.ID(1).Cols("age").Update(&User{Name:name, Age: 12})
// UPDATE user SET age = ?, updated=? Where id = ?
// force NOT update indicated columns by Omit
affected, err := engine.ID(1).Omit("name").Update(&User{Name:name, Age: 12})
// UPDATE user SET age = ?, updated=? Where id = ?
affected, err := engine.ID(1).AllCols().Update(&user)
// UPDATE user SET name=?,age=?,salt=?,passwd=?,updated=? Where id = ?
Delete
delete one or more records, Delete MUST have condition
affected, err := engine.Where(...).Delete(&user)
// DELETE FROM user Where ...
affected, err := engine.ID(2).Delete(&user)
// DELETE FROM user Where id = ?
Count
count records
counts, err := engine.Count(&user)
// SELECT count(*) AS total FROM user
FindAndCount
combines functionFind
withCount
which is usually used in query by page
var users []User
counts, err := engine.FindAndCount(&users)
Sum
sum functions
agesFloat64, err := engine.Sum(&user, "age")
// SELECT sum(age) AS total FROM user
agesInt64, err := engine.SumInt(&user, "age")
// SELECT sum(age) AS total FROM user
sumFloat64Slice, err := engine.Sums(&user, "age", "score")
// SELECT sum(age), sum(score) FROM user
sumInt64Slice, err := engine.SumsInt(&user, "age", "score")
// SELECT sum(age), sum(score) FROM user
- Query conditions builder
err := engine.Where(builder.NotIn("a", 1, 2).And(builder.In("b", "c", "d", "e"))).Find(&users)
// SELECT id, name ... FROM user WHERE a NOT IN (?, ?) AND b IN (?, ?, ?)
- Multiple operations in one go routine, no transation here but resue session memory
session := engine.NewSession()
defer session.Close()
user1 := Userinfo{Username: "xiaoxiao", Departname: "dev", Alias: "lunny", Created: time.Now()}
if _, err := session.Insert(&user1); err != nil {
return err
}
user2 := Userinfo{Username: "yyy"}
if _, err := session.Where("id = ?", 2).Update(&user2); err != nil {
return err
}
if _, err := session.Exec("delete from userinfo where username = ?", user2.Username); err != nil {
return err
}
return nil
- Transation should be on one go routine. There is transaction and resue session memory
session := engine.NewSession()
defer session.Close()
// add Begin() before any action
if err := session.Begin(); err != nil {
// if returned then will rollback automatically
return err
}
user1 := Userinfo{Username: "xiaoxiao", Departname: "dev", Alias: "lunny", Created: time.Now()}
if _, err := session.Insert(&user1); err != nil {
return err
}
user2 := Userinfo{Username: "yyy"}
if _, err := session.Where("id = ?", 2).Update(&user2); err != nil {
return err
}
if _, err := session.Exec("delete from userinfo where username = ?", user2.Username); err != nil {
return err
}
// add Commit() after all actions
return session.Commit()
- Or you can use
Transaction
to replace above codes.
res, err := engine.Transaction(func(session *xorm.Session) (interface{}, error) {
user1 := Userinfo{Username: "xiaoxiao", Departname: "dev", Alias: "lunny", Created: time.Now()}
if _, err := session.Insert(&user1); err != nil {
return nil, err
}
user2 := Userinfo{Username: "yyy"}
if _, err := session.Where("id = ?", 2).Update(&user2); err != nil {
return nil, err
}
if _, err := session.Exec("delete from userinfo where username = ?", user2.Username); err != nil {
return nil, err
}
return nil, nil
})
- Context Cache, if enabled, current query result will be cached on session and be used by next same statement on the same session.
sess := engine.NewSession()
defer sess.Close()
var context = xorm.NewMemoryContextCache()
var c2 ContextGetStruct
has, err := sess.ID(1).ContextCache(context).Get(&c2)
assert.NoError(t, err)
assert.True(t, has)
assert.EqualValues(t, 1, c2.Id)
assert.EqualValues(t, "1", c2.Name)
sql, args := sess.LastSQL()
assert.True(t, len(sql) > 0)
assert.True(t, len(args) > 0)
var c3 ContextGetStruct
has, err = sess.ID(1).ContextCache(context).Get(&c3)
assert.NoError(t, err)
assert.True(t, has)
assert.EqualValues(t, 1, c3.Id)
assert.EqualValues(t, "1", c3.Name)
sql, args = sess.LastSQL()
assert.True(t, len(sql) == 0)
assert.True(t, len(args) == 0)
Contributing
If you want to pull request, please see CONTRIBUTING. And we also provide Xorm on Google Groups to discuss.
Credits
Contributors
This project exists thanks to all the people who contribute. [Contribute].
Backers
Thank you to all our backers! 🙏 [Become a backer]
Sponsors
Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [Become a sponsor]
Changelog
-
v0.7.0
- Some bugs fixed
-
v0.6.6
- Some bugs fixed
-
v0.6.5
- Postgres schema support
- vgo support
- Add FindAndCount
- Database special params support via NewEngineWithParams
- Some bugs fixed
-
v0.6.4
- Automatical Read/Write seperatelly
- Query/QueryString/QueryInterface and action with Where/And
- Get support non-struct variables
- BufferSize on Iterate
- fix some other bugs.
Cases
LICENSE
BSD License http://creativecommons.org/licenses/BSD/