v0.1.7 Added IConnectPool interface and NoneConnectPool, SysConnectPool, SimpleConnectPool the three implements. You can choose one of them and the default is SysConnectPool. You can customrize your own connection pool. struct Engine added Close method, It should be invoked before system exit.

This commit is contained in:
Lunny Xiao 2013-07-03 11:49:29 +08:00
parent a409154166
commit fd36a7a539
18 changed files with 419 additions and 97 deletions

View File

@ -17,6 +17,7 @@ Drivers for Go's sql package which currently support database/sql includes:
## Changelog ## Changelog
* **v0.1.7** : Added IConnectPool interface and NoneConnectPool, SysConnectPool, SimpleConnectPool the three implements. You can choose one of them and the default is SysConnectPool. You can customrize your own connection pool. struct Engine added Close method, It should be invoked before system exit.
* **v0.1.6** : Added conversion interface support; added struct derive support; added single mapping support * **v0.1.6** : Added conversion interface support; added struct derive support; added single mapping support
* **v0.1.5** : Added multi threads support; added Sql() function for struct query; Get function changed return inteface; MakeSession and Create are instead with NewSession and NewEngine. * **v0.1.5** : Added multi threads support; added Sql() function for struct query; Get function changed return inteface; MakeSession and Create are instead with NewSession and NewEngine.
* **v0.1.4** : Added simple cascade load support; added more data type supports. * **v0.1.4** : Added simple cascade load support; added more data type supports.
@ -71,6 +72,10 @@ err, engine = xorm.NewEngine("sqlite3", "./test.db")
```Go ```Go
engine.ShowSQL = true engine.ShowSQL = true
``` ```
1.2 If you want to use your own connection pool
```Go
err = engine.SetPool(NewSimpleConnectPool())
```
2.Define a struct 2.Define a struct
@ -278,7 +283,9 @@ err = session.Commit()
if err != nil { if err != nil {
return return
} }
``` ```
5.Derive mapping
Please see derive.go in examples folder.
## Mapping Rules ## Mapping Rules
@ -311,6 +318,9 @@ Another is use field tag, field tag support the below keywords which split with
</tr> </tr>
<tr> <tr>
<td>unique</td><td>unique</td> <td>unique</td><td>unique</td>
</tr>
<tr>
<td>extends</td><td>used in anonymous struct means mapping this struct's fields to table</td>
</tr> </tr>
<tr> <tr>
<td>-</td><td>this field is not map as a table column</td> <td>-</td><td>this field is not map as a table column</td>

View File

@ -2,7 +2,7 @@
[English](https://github.com/lunny/xorm/blob/master/README.md) [English](https://github.com/lunny/xorm/blob/master/README.md)
xorm是一个Go语言ORM库. 通过它可以使数据库操作非常简便。 xorm是一个简单而强大的Go语言ORM库. 通过它可以使数据库操作非常简便。
[![Build Status](https://drone.io/github.com/lunny/xorm/status.png)](https://drone.io/github.com/lunny/xorm/latest) [![Build Status](https://drone.io/github.com/lunny/xorm/status.png)](https://drone.io/github.com/lunny/xorm/latest)
@ -16,6 +16,7 @@ xorm是一个Go语言的ORM库. 通过它可以使数据库操作非常简便。
## 更新日志 ## 更新日志
* **v0.1.7** : 新增IConnectPool接口以及NoneConnectPool, SysConnectPool, SimpleConnectPool三种实现可以选择不使用连接池使用系统连接池和使用自带连接池三种实现默认为SysConnectPool即系统自带的连接池。同时支持自定义连接池。Engine新增Close方法在系统退出时应调用此方法。
* **v0.1.6** : 新增Conversion支持自定义类型到数据库类型的转换新增查询结构体自动检测匿名成员支持新增单向映射支持 * **v0.1.6** : 新增Conversion支持自定义类型到数据库类型的转换新增查询结构体自动检测匿名成员支持新增单向映射支持
* **v0.1.5** : 新增对多线程的支持新增Sql()函数支持任意sql语句的struct查询Get函数返回值变动MakeSession和Create函数被NewSession和NewEngine函数替代 * **v0.1.5** : 新增对多线程的支持新增Sql()函数支持任意sql语句的struct查询Get函数返回值变动MakeSession和Create函数被NewSession和NewEngine函数替代
* **v0.1.4** : Get函数和Find函数新增简单的级联载入功能对更多的数据库类型支持。 * **v0.1.4** : Get函数和Find函数新增简单的级联载入功能对更多的数据库类型支持。
@ -26,7 +27,7 @@ xorm是一个Go语言的ORM库. 通过它可以使数据库操作非常简便。
## 特性 ## 特性
* 支持Struct和数据库表之间的映射映射方式支持命名约定和Tag两种方式 * 支持Struct和数据库表之间的映射映射方式支持命名约定和Tag两种方式,映射支持继承
* 事务支持 * 事务支持
@ -34,7 +35,12 @@ xorm是一个Go语言的ORM库. 通过它可以使数据库操作非常简便。
* 使用连写来简化调用 * 使用连写来简化调用
* 支持使用Id, In, Where, Limit, Join, Having, Table, Sql等函数和结构体等方式作为条件 * 支持使用Id, In, Where, Limit, Join, Having, Table, Sql等函数和结构体等方式作为条件
* 支持数据库连接池
* 支持级联加载struct
## 安装 ## 安装
@ -50,6 +56,7 @@ import (
"github.com/lunny/xorm" "github.com/lunny/xorm"
) )
engine, err := xorm.NewEngine("mysql", "root:123@/test?charset=utf8") engine, err := xorm.NewEngine("mysql", "root:123@/test?charset=utf8")
defer engine.Close()
``` ```
or or
@ -59,7 +66,8 @@ import (
_ "github.com/mattn/go-sqlite3" _ "github.com/mattn/go-sqlite3"
"github.com/lunny/xorm" "github.com/lunny/xorm"
) )
engine, err = xorm.NewEngine("sqlite3", "./test.db") engine, err = xorm.NewEngine("sqlite3", "./test.db")
defer engine.Close()
``` ```
1.1.默认将不会显示自动生成的SQL语句如果要显示则需要设置 1.1.默认将不会显示自动生成的SQL语句如果要显示则需要设置
@ -67,6 +75,11 @@ engine, err = xorm.NewEngine("sqlite3", "./test.db")
```Go ```Go
engine.ShowSQL = true engine.ShowSQL = true
``` ```
1.2.如果要更换连接池实现可使用SetPool方法
```Go
err = engine.SetPool(NewSimpleConnectPool())
```
2.所有的ORM操作都针对一个或多个结构体一个结构体对应一张表定义一个结构体如下 2.所有的ORM操作都针对一个或多个结构体一个结构体对应一张表定义一个结构体如下
@ -272,6 +285,10 @@ if err != nil {
return return
} }
``` ```
5.匿名结构体继承:
请查看Examples中的derive.go文件。
## 映射规则 ## 映射规则
@ -305,6 +322,9 @@ UserInfo中的成员UserName将会自动对应名为user_name的字段。
<tr> <tr>
<td>unique</td><td>是否是唯一</td> <td>unique</td><td>是否是唯一</td>
</tr> </tr>
<tr>
<td>extends</td><td>应用于一个匿名结构体之上,表示此匿名结构体的成员也映射到数据库中</td>
</tr>
<tr> <tr>
<td>-</td><td>这个Field将不进行字段映射</td> <td>-</td><td>这个Field将不进行字段映射</td>
</tr> </tr>

1
VERSION Normal file
View File

@ -0,0 +1 @@
xorm v0.1.7

View File

@ -1,14 +1,20 @@
// Copyright 2013 The XORM Authors. All rights reserved.
// Use of this source code is governed by a BSD
// license that can be found in the LICENSE file.
// Package xorm provides is a simple and powerful ORM for Go. It makes your
// database operation simple.
// Warning: All contents in this file will be removed from xorm some times after
package xorm package xorm
// all content in this file will be removed from xorm some times after // @deprecated : please use NewSession instead
// @deprecation : please use NewSession instead
func (engine *Engine) MakeSession() (Session, error) { func (engine *Engine) MakeSession() (Session, error) {
s := engine.NewSession() s := engine.NewSession()
return *s, nil return *s, nil
} }
// @deprecation : please use NewEngine instead // @deprecated : please use NewEngine instead
func Create(driverName string, dataSourceName string) Engine { func Create(driverName string, dataSourceName string) Engine {
engine, _ := NewEngine(driverName, dataSourceName) engine, _ := NewEngine(driverName, dataSourceName)
return *engine return *engine

View File

@ -1,3 +1,10 @@
// Copyright 2013 The XORM Authors. All rights reserved.
// Use of this source code is governed by a BSD
// license that can be found in the LICENSE file.
// Package xorm provides is a simple and powerful ORM for Go. It makes your
// database operation simple.
package xorm package xorm
import ( import (
@ -19,21 +26,39 @@ const (
type dialect interface { type dialect interface {
SqlType(t *Column) string SqlType(t *Column) string
SupportInsertMany() bool
QuoteIdentifier() string
AutoIncrIdentifier() string
} }
type Engine struct { type Engine struct {
Mapper IMapper Mapper IMapper
TagIdentifier string TagIdentifier string
DriverName string DriverName string
DataSourceName string DataSourceName string
Dialect dialect Dialect dialect
Tables map[reflect.Type]*Table Tables map[reflect.Type]*Table
mutex *sync.Mutex mutex *sync.Mutex
AutoIncrement string ShowSQL bool
ShowSQL bool pool IConnectPool
InsertMany bool CacheMapping bool
QuoteIdentifier string }
Pool IConnectionPool
func (engine *Engine) SupportInsertMany() bool {
return engine.Dialect.SupportInsertMany()
}
func (engine *Engine) QuoteIdentifier() string {
return engine.Dialect.QuoteIdentifier()
}
func (engine *Engine) AutoIncrIdentifier() string {
return engine.Dialect.AutoIncrIdentifier()
}
func (engine *Engine) SetPool(pool IConnectPool) error {
engine.pool = pool
return engine.pool.Init(engine)
} }
func Type(bean interface{}) reflect.Type { func Type(bean interface{}) reflect.Type {
@ -58,9 +83,16 @@ func (engine *Engine) NewSession() *Session {
return session return session
} }
func (engine *Engine) Close() error {
return engine.pool.Close(engine)
}
func (engine *Engine) Test() error { func (engine *Engine) Test() error {
session := engine.NewSession() session := engine.NewSession()
defer session.Close() defer session.Close()
if engine.ShowSQL {
fmt.Printf("PING DATABASE %v\n", engine.DriverName)
}
return session.Ping() return session.Ping()
} }
@ -264,9 +296,7 @@ func (engine *Engine) Map(beans ...interface{}) (e error) {
defer engine.mutex.Unlock() defer engine.mutex.Unlock()
for _, bean := range beans { for _, bean := range beans {
t := Type(bean) t := Type(bean)
if _, ok := engine.Tables[t]; !ok { engine.Tables[t] = engine.MapType(t)
engine.Tables[t] = engine.MapType(t)
}
} }
return return
} }
@ -305,6 +335,7 @@ func (e *Engine) CreateTables(beans ...interface{}) error {
if err != nil { if err != nil {
return err return err
} }
for _, bean := range beans { for _, bean := range beans {
err = session.CreateTable(bean) err = session.CreateTable(bean)
if err != nil { if err != nil {

View File

@ -32,6 +32,7 @@ func main() {
fmt.Println(err) fmt.Println(err)
return return
} }
defer Orm.Close()
Orm.ShowSQL = true Orm.ShowSQL = true
err = Orm.CreateTables(&User{}, &LoginInfo{}) err = Orm.CreateTables(&User{}, &LoginInfo{})
if err != nil { if err != nil {

View File

@ -7,7 +7,7 @@ import (
_ "github.com/mattn/go-sqlite3" _ "github.com/mattn/go-sqlite3"
"os" "os"
//"time" //"time"
"sync/atomic" //"sync/atomic"
xorm "xorm" xorm "xorm"
) )
@ -78,23 +78,29 @@ func test(engine *xorm.Engine) {
<-queue <-queue
} }
conns := atomic.LoadInt32(&xorm.ConnectionNum) //conns := atomic.LoadInt32(&xorm.ConnectionNum)
fmt.Println("connection number:", conns) //fmt.Println("connection number:", conns)
fmt.Println("end") fmt.Println("end")
} }
func main() { func main() {
fmt.Println("create engine")
engine, err := sqliteEngine() engine, err := sqliteEngine()
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
return return
} }
engine.ShowSQL = true
fmt.Println(engine)
test(engine) test(engine)
fmt.Println("test end")
engine.Close()
engine, err = mysqlEngine() engine, err = mysqlEngine()
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
return return
} }
defer engine.Close()
test(engine) test(engine)
} }

45
examples/pool.go Normal file
View File

@ -0,0 +1,45 @@
package main
import (
"fmt"
_ "github.com/mattn/go-sqlite3"
"os"
. "xorm"
)
type User struct {
Id int64
Name string
}
func main() {
f := "pool.db"
os.Remove(f)
Orm, err := NewEngine("sqlite3", f)
if err != nil {
fmt.Println(err)
return
}
err = Orm.SetPool(NewSimpleConnectPool())
if err != nil {
fmt.Println(err)
return
}
Orm.ShowSQL = true
err = Orm.CreateTables(&User{})
if err != nil {
fmt.Println(err)
return
}
for i := 0; i < 10; i++ {
_, err = Orm.Get(&User{})
if err != nil {
fmt.Println(err)
break
}
}
}

View File

@ -1,3 +1,10 @@
// Copyright 2013 The XORM Authors. All rights reserved.
// Use of this source code is governed by a BSD
// license that can be found in the LICENSE file.
// Package xorm provides is a simple and powerful ORM for Go. It makes your
// database operation simple.
package xorm package xorm
import ( import (

View File

@ -1,3 +1,10 @@
// Copyright 2013 The XORM Authors. All rights reserved.
// Use of this source code is governed by a BSD
// license that can be found in the LICENSE file.
// Package xorm provides is a simple and powerful ORM for Go. It makes your
// database operation simple.
package xorm package xorm
import "strconv" import "strconv"
@ -5,7 +12,7 @@ import "strconv"
type mysql struct { type mysql struct {
} }
func (db mysql) SqlType(c *Column) string { func (db *mysql) SqlType(c *Column) string {
switch t := c.SQLType; t { switch t := c.SQLType; t {
case Date, DateTime, TimeStamp: case Date, DateTime, TimeStamp:
return "DATETIME" return "DATETIME"
@ -17,3 +24,15 @@ func (db mysql) SqlType(c *Column) string {
return t.Name return t.Name
} }
} }
func (db *mysql) SupportInsertMany() bool {
return true
}
func (db *mysql) QuoteIdentifier() string {
return "`"
}
func (db *mysql) AutoIncrIdentifier() string {
return "AUTO_INCREMENT"
}

View File

@ -14,7 +14,7 @@ utf8 COLLATE utf8_general_ci;
func TestMysql(t *testing.T) { func TestMysql(t *testing.T) {
// You should drop all tables before executing this testing // You should drop all tables before executing this testing
me = Create("mysql", "root:@/xorm_test?charset=utf8") me = Create("mysql", "root:123@/test?charset=utf8")
me.ShowSQL = true me.ShowSQL = true
directCreateTable(&me, t) directCreateTable(&me, t)

196
pool.go
View File

@ -1,81 +1,207 @@
// Copyright 2013 The XORM Authors. All rights reserved.
// Use of this source code is governed by a BSD
// license that can be found in the LICENSE file.
// Package xorm provides is a simple and powerful ORM for Go. It makes your
// database operation simple.
// This file contains a connection pool interafce and two implements. One is
// NoneConnectionPool is for direct connecting, another is a simple connection
// pool by lock. Attention, the driver may has provided connection pool itself.
// So the default pool is NoneConnectionPool.
package xorm package xorm
import ( import (
"database/sql" "database/sql"
//"fmt" //"fmt"
//"sync" "sync"
"sync/atomic" //"sync/atomic"
//"time" "time"
) )
type IConnectionPool interface { // Interface IConnecPool is a connection pool interface, all implements should implement
// Init, RetrieveDB, ReleaseDB and Close methods.
// Init for init when engine be created or invoke SetPool
// RetrieveDB for requesting a connection to db;
// ReleaseDB for releasing a db connection;
// Close for invoking when engine.Close
type IConnectPool interface {
Init(engine *Engine) error
RetrieveDB(engine *Engine) (*sql.DB, error) RetrieveDB(engine *Engine) (*sql.DB, error)
ReleaseDB(engine *Engine, db *sql.DB) ReleaseDB(engine *Engine, db *sql.DB)
Close(engine *Engine) error
SetMaxIdleConns(conns int)
MaxIdleConns() int
} }
// Struct NoneConnectPool is a implement for IConnectPool. It provides directly invoke driver's
// open and release connection function
type NoneConnectPool struct { type NoneConnectPool struct {
} }
var ConnectionNum int32 = 0 // NewNoneConnectPool new a NoneConnectPool.
func NewNoneConnectPool() IConnectPool {
return &NoneConnectPool{}
}
func (p NoneConnectPool) RetrieveDB(engine *Engine) (db *sql.DB, err error) { // Init do nothing
atomic.AddInt32(&ConnectionNum, 1) func (p *NoneConnectPool) Init(engine *Engine) error {
return nil
}
// RetrieveDB directly open a connection
func (p *NoneConnectPool) RetrieveDB(engine *Engine) (db *sql.DB, err error) {
db, err = engine.OpenDB() db, err = engine.OpenDB()
//fmt.Printf("--open a connection--%x\n", &db)
return return
} }
func (p NoneConnectPool) ReleaseDB(engine *Engine, db *sql.DB) { // ReleaseDB directly close a connection
atomic.AddInt32(&ConnectionNum, -1) func (p *NoneConnectPool) ReleaseDB(engine *Engine, db *sql.DB) {
//fmt.Printf("--close a connection--%x\n", &db)
db.Close() db.Close()
} }
/*type SimpleConnectPool struct { // Close do nothing
releasedSessions []*sql.DB func (p *NoneConnectPool) Close(engine *Engine) error {
cur int return nil
usingSessions map[*sql.DB]time.Time
maxWaitTimeOut int
mutex *sync.Mutex
} }
func (p SimpleConnectPool) RetrieveDB(engine *Engine) (*sql.DB, error) { func (p *NoneConnectPool) SetMaxIdleConns(conns int) {
}
func (p *NoneConnectPool) MaxIdleConns() int {
return 0
}
// Struct SysConnectPool is a simple wrapper for using system default connection pool.
// About the system connection pool, you can review the code database/sql/sql.go
// It's currently default Pool implments.
type SysConnectPool struct {
db *sql.DB
maxIdleConns int
}
// NewSysConnectPool new a SysConnectPool.
func NewSysConnectPool() IConnectPool {
return &SysConnectPool{}
}
// Init create a db immediately and keep it util engine closed.
func (s *SysConnectPool) Init(engine *Engine) error {
db, err := engine.OpenDB()
if err != nil {
return err
}
s.db = db
s.maxIdleConns = 2
return nil
}
// RetrieveDB just return the only db
func (p *SysConnectPool) RetrieveDB(engine *Engine) (db *sql.DB, err error) {
return p.db, nil
}
// ReleaseDB do nothing
func (p *SysConnectPool) ReleaseDB(engine *Engine, db *sql.DB) {
}
// Close closed the only db
func (p *SysConnectPool) Close(engine *Engine) error {
return p.db.Close()
}
func (p *SysConnectPool) SetMaxIdleConns(conns int) {
p.db.SetMaxIdleConns(conns)
p.maxIdleConns = conns
}
func (p *SysConnectPool) MaxIdleConns() int {
return p.maxIdleConns
}
// NewSimpleConnectPool new a SimpleConnectPool
func NewSimpleConnectPool() IConnectPool {
return &SimpleConnectPool{releasedConnects: make([]*sql.DB, 10),
usingConnects: map[*sql.DB]time.Time{},
cur: -1,
maxWaitTimeOut: 14400,
maxIdleConns: 10,
mutex: &sync.Mutex{},
}
}
// Struct SimpleConnectPool is a simple implementation for IConnectPool.
// It's a custom connection pool and not use system connection pool.
// Opening or Closing a database connection must be enter a lock.
// This implements will be improved in furture.
type SimpleConnectPool struct {
releasedConnects []*sql.DB
cur int
usingConnects map[*sql.DB]time.Time
maxWaitTimeOut int
mutex *sync.Mutex
maxIdleConns int
}
func (s *SimpleConnectPool) Init(engine *Engine) error {
return nil
}
// RetrieveDB get a connection from connection pool
func (p *SimpleConnectPool) RetrieveDB(engine *Engine) (*sql.DB, error) {
p.mutex.Lock() p.mutex.Lock()
defer p.mutex.Unlock() defer p.mutex.Unlock()
var db *sql.DB = nil var db *sql.DB = nil
var err error = nil var err error = nil
fmt.Printf("%x, rbegin - released:%v, using:%v\n", &p, p.cur+1, len(p.usingSessions)) //fmt.Printf("%x, rbegin - released:%v, using:%v\n", &p, p.cur+1, len(p.usingConnects))
if p.cur < 0 { if p.cur < 0 {
ConnectionNum = ConnectionNum + 1
fmt.Printf("new %v\n", ConnectionNum)
db, err = engine.OpenDB() db, err = engine.OpenDB()
if err != nil { if err != nil {
return nil, err return nil, err
} }
p.usingSessions[db] = time.Now() p.usingConnects[db] = time.Now()
} else { } else {
db = p.releasedSessions[p.cur] db = p.releasedConnects[p.cur]
p.usingSessions[db] = time.Now() p.usingConnects[db] = time.Now()
p.releasedSessions[p.cur] = nil p.releasedConnects[p.cur] = nil
p.cur = p.cur - 1 p.cur = p.cur - 1
fmt.Println("release one")
} }
fmt.Printf("%x, rend - released:%v, using:%v\n", &p, p.cur+1, len(p.usingSessions)) //fmt.Printf("%x, rend - released:%v, using:%v\n", &p, p.cur+1, len(p.usingConnects))
return db, nil return db, nil
} }
func (p SimpleConnectPool) ReleaseDB(engine *Engine, db *sql.DB) { // ReleaseDB release a db from connection pool
func (p *SimpleConnectPool) ReleaseDB(engine *Engine, db *sql.DB) {
p.mutex.Lock() p.mutex.Lock()
defer p.mutex.Unlock() defer p.mutex.Unlock()
fmt.Printf("%x, lbegin - released:%v, using:%v\n", &p, p.cur+1, len(p.usingSessions)) //fmt.Printf("%x, lbegin - released:%v, using:%v\n", &p, p.cur+1, len(p.usingConnects))
if p.cur >= 29 { if p.cur >= p.maxIdleConns-1 {
ConnectionNum = ConnectionNum - 1
db.Close() db.Close()
} else { } else {
p.cur = p.cur + 1 p.cur = p.cur + 1
p.releasedSessions[p.cur] = db p.releasedConnects[p.cur] = db
} }
delete(p.usingSessions, db) delete(p.usingConnects, db)
fmt.Printf("%x, lend - released:%v, using:%v\n", &p, p.cur+1, len(p.usingSessions)) //fmt.Printf("%x, lend - released:%v, using:%v\n", &p, p.cur+1, len(p.usingConnects))
}*/ }
// Close release all db
func (p *SimpleConnectPool) Close(engine *Engine) error {
p.mutex.Lock()
defer p.mutex.Unlock()
for len(p.releasedConnects) > 0 {
p.releasedConnects[0].Close()
p.releasedConnects = p.releasedConnects[1:]
}
return nil
}
func (p *SimpleConnectPool) SetMaxIdleConns(conns int) {
p.maxIdleConns = conns
}
func (p *SimpleConnectPool) MaxIdleConns() int {
return p.maxIdleConns
}

View File

@ -1,3 +1,10 @@
// Copyright 2013 The XORM Authors. All rights reserved.
// Use of this source code is governed by a BSD
// license that can be found in the LICENSE file.
// Package xorm provides is a simple and powerful ORM for Go. It makes your
// database operation simple.
package xorm package xorm
import ( import (
@ -29,7 +36,7 @@ func (session *Session) Init() {
func (session *Session) Close() { func (session *Session) Close() {
defer func() { defer func() {
if session.Db != nil { if session.Db != nil {
session.Engine.Pool.ReleaseDB(session.Engine, session.Db) session.Engine.pool.ReleaseDB(session.Engine, session.Db)
session.Db = nil session.Db = nil
session.Tx = nil session.Tx = nil
session.Init() session.Init()
@ -97,7 +104,7 @@ func (session *Session) Having(conditions string) *Session {
func (session *Session) newDb() error { func (session *Session) newDb() error {
if session.Db == nil { if session.Db == nil {
db, err := session.Engine.Pool.RetrieveDB(session.Engine) db, err := session.Engine.pool.RetrieveDB(session.Engine)
if err != nil { if err != nil {
return err return err
} }
@ -571,7 +578,7 @@ func (session *Session) Insert(beans ...interface{}) (int64, error) {
for _, bean := range beans { for _, bean := range beans {
sliceValue := reflect.Indirect(reflect.ValueOf(bean)) sliceValue := reflect.Indirect(reflect.ValueOf(bean))
if sliceValue.Kind() == reflect.Slice { if sliceValue.Kind() == reflect.Slice {
if session.Engine.InsertMany { if session.Engine.SupportInsertMany() {
lastId, err = session.InsertMulti(bean) lastId, err = session.InsertMulti(bean)
if err != nil { if err != nil {
if !isInTransaction { if !isInTransaction {
@ -642,7 +649,7 @@ func (session *Session) InsertMulti(rowsSlicePtr interface{}) (int64, error) {
} }
if table, ok := session.Engine.Tables[fieldValue.Type()]; ok { if table, ok := session.Engine.Tables[fieldValue.Type()]; ok {
pkField := reflect.Indirect(fieldValue).FieldByName(table.PKColumn().FieldName) pkField := reflect.Indirect(fieldValue).FieldByName(table.PKColumn().FieldName)
fmt.Println(pkField.Interface()) //fmt.Println(pkField.Interface())
args = append(args, pkField.Interface()) args = append(args, pkField.Interface())
} else { } else {
args = append(args, val) args = append(args, val)
@ -674,9 +681,9 @@ func (session *Session) InsertMulti(rowsSlicePtr interface{}) (int64, error) {
} }
statement := fmt.Sprintf("INSERT INTO %v%v%v (%v) VALUES (%v)", statement := fmt.Sprintf("INSERT INTO %v%v%v (%v) VALUES (%v)",
session.Engine.QuoteIdentifier, session.Engine.QuoteIdentifier(),
session.Statement.TableName(), session.Statement.TableName(),
session.Engine.QuoteIdentifier, session.Engine.QuoteIdentifier(),
strings.Join(colNames, ", "), strings.Join(colNames, ", "),
strings.Join(colMultiPlaces, "),(")) strings.Join(colMultiPlaces, "),("))
@ -696,6 +703,7 @@ func (session *Session) InsertMulti(rowsSlicePtr interface{}) (int64, error) {
func (session *Session) InsertOne(bean interface{}) (int64, error) { func (session *Session) InsertOne(bean interface{}) (int64, error) {
table := session.Engine.AutoMap(bean) table := session.Engine.AutoMap(bean)
//fmt.Printf("table: %v\n", table)
session.Statement.RefTable = table session.Statement.RefTable = table
colNames := make([]string, 0) colNames := make([]string, 0)
colPlaces := make([]string, 0) colPlaces := make([]string, 0)
@ -736,9 +744,9 @@ func (session *Session) InsertOne(bean interface{}) (int64, error) {
} }
sql := fmt.Sprintf("INSERT INTO %v%v%v (%v) VALUES (%v)", sql := fmt.Sprintf("INSERT INTO %v%v%v (%v) VALUES (%v)",
session.Engine.QuoteIdentifier, session.Engine.QuoteIdentifier(),
session.Statement.TableName(), session.Statement.TableName(),
session.Engine.QuoteIdentifier, session.Engine.QuoteIdentifier(),
strings.Join(colNames, ", "), strings.Join(colNames, ", "),
strings.Join(colPlaces, ", ")) strings.Join(colPlaces, ", "))
@ -801,9 +809,9 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6
} }
sql := fmt.Sprintf("UPDATE %v%v%v SET %v %v", sql := fmt.Sprintf("UPDATE %v%v%v SET %v %v",
session.Engine.QuoteIdentifier, session.Engine.QuoteIdentifier(),
session.Statement.TableName(), session.Statement.TableName(),
session.Engine.QuoteIdentifier, session.Engine.QuoteIdentifier(),
strings.Join(colNames, ", "), strings.Join(colNames, ", "),
condition) condition)
@ -840,9 +848,9 @@ func (session *Session) Delete(bean interface{}) (int64, error) {
} }
statement := fmt.Sprintf("DELETE FROM %v%v%v %v", statement := fmt.Sprintf("DELETE FROM %v%v%v %v",
session.Engine.QuoteIdentifier, session.Engine.QuoteIdentifier(),
session.Statement.TableName(), session.Statement.TableName(),
session.Engine.QuoteIdentifier, session.Engine.QuoteIdentifier(),
condition) condition)
res, err := session.Exec(statement, append(st.Params, args...)...) res, err := session.Exec(statement, append(st.Params, args...)...)

View File

@ -1,9 +1,16 @@
// Copyright 2013 The XORM Authors. All rights reserved.
// Use of this source code is governed by a BSD
// license that can be found in the LICENSE file.
// Package xorm provides is a simple and powerful ORM for Go. It makes your
// database operation simple.
package xorm package xorm
type sqlite3 struct { type sqlite3 struct {
} }
func (db sqlite3) SqlType(c *Column) string { func (db *sqlite3) SqlType(c *Column) string {
switch t := c.SQLType; t { switch t := c.SQLType; t {
case Date, DateTime, TimeStamp: case Date, DateTime, TimeStamp:
return "NUMERIC" return "NUMERIC"
@ -21,3 +28,15 @@ func (db sqlite3) SqlType(c *Column) string {
return t.Name return t.Name
} }
} }
func (db *sqlite3) SupportInsertMany() bool {
return true
}
func (db *sqlite3) QuoteIdentifier() string {
return "`"
}
func (db *sqlite3) AutoIncrIdentifier() string {
return "AUTOINCREMENT"
}

View File

@ -1,3 +1,10 @@
// Copyright 2013 The XORM Authors. All rights reserved.
// Use of this source code is governed by a BSD
// license that can be found in the LICENSE file.
// Package xorm provides is a simple and powerful ORM for Go. It makes your
// database operation simple.
package xorm package xorm
import ( import (
@ -104,7 +111,8 @@ func BuildConditions(engine *Engine, table *Table, bean interface{}) ([]string,
} else { } else {
args = append(args, val) args = append(args, val)
} }
colNames = append(colNames, engine.QuoteIdentifier+col.Name+engine.QuoteIdentifier+"=?") colNames = append(colNames, fmt.Sprintf("%v%v%v = ?", engine.QuoteIdentifier(),
col.Name, engine.QuoteIdentifier()))
} }
return colNames, args return colNames, args
@ -114,6 +122,7 @@ func (statement *Statement) TableName() string {
if statement.AltTableName != "" { if statement.AltTableName != "" {
return statement.AltTableName return statement.AltTableName
} }
if statement.RefTable != nil { if statement.RefTable != nil {
return statement.RefTable.Name return statement.RefTable.Name
} }
@ -179,7 +188,7 @@ func (statement *Statement) genColumnStr(col *Column) string {
} }
if col.IsAutoIncrement { if col.IsAutoIncrement {
sql += statement.Engine.AutoIncrement + " " sql += statement.Engine.AutoIncrIdentifier() + " "
} }
if col.Nullable { if col.Nullable {

View File

@ -1,3 +1,10 @@
// Copyright 2013 The XORM Authors. All rights reserved.
// Use of this source code is governed by a BSD
// license that can be found in the LICENSE file.
// Package xorm provides is a simple and powerful ORM for Go. It makes your
// database operation simple.
package xorm package xorm
import ( import (

View File

@ -107,7 +107,7 @@ func insertAutoIncr(engine *Engine, t *testing.T) {
} }
func insertMulti(engine *Engine, t *testing.T) { func insertMulti(engine *Engine, t *testing.T) {
engine.InsertMany = true //engine.InsertMany = true
users := []Userinfo{ users := []Userinfo{
{Username: "xlw", Departname: "dev", Alias: "lunny2", Created: time.Now()}, {Username: "xlw", Departname: "dev", Alias: "lunny2", Created: time.Now()},
{Username: "xlw2", Departname: "dev", Alias: "lunny3", Created: time.Now()}, {Username: "xlw2", Departname: "dev", Alias: "lunny3", Created: time.Now()},
@ -119,7 +119,7 @@ func insertMulti(engine *Engine, t *testing.T) {
t.Error(err) t.Error(err)
} }
engine.InsertMany = false /*engine.InsertMany = false
users = []Userinfo{ users = []Userinfo{
{Username: "xlw9", Departname: "dev", Alias: "lunny9", Created: time.Now()}, {Username: "xlw9", Departname: "dev", Alias: "lunny9", Created: time.Now()},
@ -132,7 +132,7 @@ func insertMulti(engine *Engine, t *testing.T) {
t.Error(err) t.Error(err)
} }
engine.InsertMany = true engine.InsertMany = true*/
} }
func insertTwoTable(engine *Engine, t *testing.T) { func insertTwoTable(engine *Engine, t *testing.T) {

37
xorm.go
View File

@ -1,3 +1,10 @@
// Copyright 2013 The XORM Authors. All rights reserved.
// Use of this source code is governed by a BSD
// license that can be found in the LICENSE file.
// Package xorm provides is a simple and powerful ORM for Go. It makes your
// database operation simple.
package xorm package xorm
import ( import (
@ -9,34 +16,34 @@ import (
//"time" //"time"
) )
const (
version string = "0.1.6"
)
func NewEngine(driverName string, dataSourceName string) (*Engine, error) { func NewEngine(driverName string, dataSourceName string) (*Engine, error) {
engine := &Engine{ShowSQL: false, DriverName: driverName, Mapper: SnakeMapper{}, engine := &Engine{ShowSQL: false, DriverName: driverName, Mapper: SnakeMapper{},
DataSourceName: dataSourceName} DataSourceName: dataSourceName}
engine.Tables = make(map[reflect.Type]*Table) engine.Tables = make(map[reflect.Type]*Table)
engine.mutex = &sync.Mutex{} engine.mutex = &sync.Mutex{}
engine.InsertMany = true //engine.InsertMany = true
engine.TagIdentifier = "xorm" engine.TagIdentifier = "xorm"
engine.QuoteIdentifier = "`" //engine.QuoteIdentifier = "`"
if driverName == SQLITE { if driverName == SQLITE {
engine.Dialect = sqlite3{} engine.Dialect = &sqlite3{}
engine.AutoIncrement = "AUTOINCREMENT" //engine.AutoIncrement = "AUTOINCREMENT"
//engine.Pool = NoneConnectPool{} //engine.Pool = NoneConnectPool{}
} else if driverName == MYSQL { } else if driverName == MYSQL {
engine.Dialect = mysql{} engine.Dialect = &mysql{}
engine.AutoIncrement = "AUTO_INCREMENT" //engine.AutoIncrement = "AUTO_INCREMENT"
} else { } else {
return nil, errors.New(fmt.Sprintf("Unsupported driver name: %v", driverName)) return nil, errors.New(fmt.Sprintf("Unsupported driver name: %v", driverName))
} }
/*engine.Pool = &SimpleConnectPool{ //engine.Pool = NewSimpleConnectPool()
releasedSessions: make([]*sql.DB, 30), //engine.Pool = NewNoneConnectPool()
usingSessions: map[*sql.DB]time.Time{}, engine.pool = NewSysConnectPool()
cur: -1, err := engine.pool.Init(engine)
maxWaitTimeOut: 14400,
mutex: &sync.Mutex{},
}*/
engine.Pool = &NoneConnectPool{}
return engine, nil return engine, err
} }