diff --git a/docs/QuickStart.md b/docs/QuickStart.md
index 276604db..46ba4d9f 100644
--- a/docs/QuickStart.md
+++ b/docs/QuickStart.md
@@ -70,6 +70,8 @@ xorm supports four drivers now:
* Postgres: [github.com/lib/pq](https://github.com/lib/pq)
+* MsSql: [github.com/lunny/godbc](https://githubcom/lunny/godbc)
+
NewEngine's parameters are the same as `sql.Open`. So you should read the drivers' document for parameters' usage.
After engine created, you can do some settings.
@@ -100,7 +102,7 @@ engine.Logger = f
## 2.Define struct
-xorm map a struct to a database table, the rule is below.
+xorm maps a struct to a database table, the rule is below.
### 2.1.name mapping rule
@@ -113,10 +115,10 @@ SnakeMapper is the default.
engine.SetMapper(SameMapper{})
```
-同时需要注意的是:
+And you should notice:
-* 如果你使用了别的命名规则映射方案,也可以自己实现一个IMapper。
-* 表名称和字段名称的映射规则默认是相同的,当然也可以设置为不同,如:
+* If you want to use other mapping rule, implement IMapper
+* Tables's mapping rule could be different from Columns':
```Go
engine.SetTableMapper(SameMapper{})
@@ -124,7 +126,7 @@ engine.SetColumnMapper(SnakeMapper{})
```
-### 2.2.前缀映射规则,后缀映射规则和缓存映射规则
+### 2.2.Prefix mapping, Suffix Mapping and Cache Mapping
* 通过`engine.NewPrefixMapper(SnakeMapper{}, "prefix")`可以在SnakeMapper的基础上在命名中添加统一的前缀,当然也可以把SnakeMapper{}换成SameMapper或者你自定义的Mapper。
* 通过`engine.NewSufffixMapper(SnakeMapper{}, "suffix")`可以在SnakeMapper的基础上在命名中添加统一的后缀,当然也可以把SnakeMapper{}换成SameMapper或者你自定义的Mapper。
@@ -133,14 +135,15 @@ engine.SetColumnMapper(SnakeMapper{})
当然,如果你使用了别的命名规则映射方案,也可以自己实现一个IMapper。
-### 2.3.使用Table和Tag改变名称映射
+### 2.3.Tag mapping
如果所有的命名都是按照IMapper的映射来操作的,那当然是最理想的。但是如果碰到某个表名或者某个字段名跟映射规则不匹配时,我们就需要别的机制来改变。
通过`engine.Table()`方法可以改变struct对应的数据库表的名称,通过sturct中field对应的Tag中使用`xorm:"'table_name'"`可以使该field对应的Column名称为指定名称。这里使用两个单引号将Column名称括起来是为了防止名称冲突,因为我们在Tag中还可以对这个Column进行更多的定义。如果名称不冲突的情况,单引号也可以不使用。
-### 2.4.Column属性定义
+### 2.4.Column defenition
+
我们在field对应的Tag中对Column的一些属性进行定义,定义的方法基本和我们写SQL定义表结构类似,比如:
```
@@ -150,37 +153,37 @@ type User struct {
}
```
-对于不同的数据库系统,数据类型其实是有些差异的。因此xorm中对数据类型有自己的定义,基本的原则是尽量兼容各种数据库的字段类型,具体的字段对应关系可以查看[字段类型对应表](https://github.com/go-xorm/xorm/blob/master/docs/COLUMNTYPE.md)。
+For different DBMS, data types对于不同的数据库系统,数据类型其实是有些差异的。因此xorm中对数据类型有自己的定义,基本的原则是尽量兼容各种数据库的字段类型,具体的字段对应关系可以查看[字段类型对应表](https://github.com/go-xorm/xorm/blob/master/docs/COLUMNTYPE.md)。
具体的映射规则如下,另Tag中的关键字均不区分大小写,字段名区分大小写:
- name | 当前field对应的字段的名称,可选,如不写,则自动根据field名字和转换规则命名 |
+ name or 'name' | Column Name, optional |
- pk | 是否是Primary Key,当前仅支持int64类型 |
+ pk | If column is Primary Key |
当前支持30多种字段类型,详情参见 [字段类型](https://github.com/go-xorm/xorm/blob/master/docs/COLUMNTYPE.md) | 字段类型 |
- autoincr | 是否是自增 |
+ autoincr | If autoincrement column |
- [not ]null | 是否可以为空 |
+ [not ]null | notnull | if column could be blank |
- unique或unique(uniquename) | 是否是唯一,如不加括号则该字段不允许重复;如加上括号,则括号中为联合唯一索引的名字,此时如果有另外一个或多个字段和本unique的uniquename相同,则这些uniquename相同的字段组成联合唯一索引 |
+ unique/unique(uniquename) | 是否是唯一,如不加括号则该字段不允许重复;如加上括号,则括号中为联合唯一索引的名字,此时如果有另外一个或多个字段和本unique的uniquename相同,则这些uniquename相同的字段组成联合唯一索引 |
- index或index(indexname) | 是否是索引,如不加括号则该字段自身为索引,如加上括号,则括号中为联合索引的名字,此时如果有另外一个或多个字段和本index的indexname相同,则这些indexname相同的字段组成联合索引 |
+ index/index(indexname) | 是否是索引,如不加括号则该字段自身为索引,如加上括号,则括号中为联合索引的名字,此时如果有另外一个或多个字段和本index的indexname相同,则这些indexname相同的字段组成联合索引 |
extends | 应用于一个匿名结构体之上,表示此匿名结构体的成员也映射到数据库中 |
- - | 这个Field将不进行字段映射 |
+ - | This field will not be mapping |
-> | 这个Field将只写入到数据库而不从数据库读取 |
@@ -198,7 +201,7 @@ type User struct {
version | This field will be filled 1 on insert and autoincrement on update |
- default 0 | 设置默认值,紧跟的内容如果是Varchar等需要加上单引号 |
+ default 0 | default 'name' | column default value |
@@ -224,13 +227,13 @@ type Conversion interface {
xorm提供了一些动态获取和修改表结构的方法。对于一般的应用,很少动态修改表结构,则只需调用Sync()同步下表结构即可。
-## 3.1 获取数据库信息
+## 3.1 retrieve database meta info
* DBMetas()
xorm支持获取表结构信息,通过调用`engine.DBMetas()`可以获取到所有的表的信息
-## 3.2.表操作
+## 3.2.directly table operation
* CreateTables()
创建表使用`engine.CreateTables()`,参数为一个或多个空的对应Struct的指针。同时可用的方法有Charset()和StoreEngine(),如果对应的数据库支持,这两个方法可以在创建表时指定表的字符编码和使用的引擎。当前仅支持Mysql数据库。
@@ -245,7 +248,7 @@ xorm支持获取表结构信息,通过调用`engine.DBMetas()`可以获取到
删除表使用`engine.DropTables()`,参数为一个或多个空的对应Struct的指针或者表的名字。如果为string传入,则只删除对应的表,如果传入的为Struct,则删除表的同时还会删除对应的索引。
-## 3.3.创建索引和唯一索引
+## 3.3.create indexes and uniques
* CreateIndexes
根据struct中的tag来创建索引
diff --git a/engine.go b/engine.go
index b375e2a7..3cf5fc66 100644
--- a/engine.go
+++ b/engine.go
@@ -90,14 +90,8 @@ func (engine *Engine) AutoIncrStr() string {
return engine.dialect.AutoIncrStr()
}
-// Set engine's pool, the pool default is Go's standard library's connection pool.
-/*func (engine *Engine) SetPool(pool IConnectPool) error {
- engine.Pool = pool
- return engine.Pool.Init(engine)
-}*/
-
-// SetMaxConns is only available for go 1.2+
-func (engine *Engine) SetMaxConns(conns int) {
+// SetMaxOpenConns is only available for go 1.2+
+func (engine *Engine) SetMaxOpenConns(conns int) {
engine.db.SetMaxOpenConns(conns)
}
@@ -141,6 +135,10 @@ func (engine *Engine) DB() *core.DB {
return engine.db
}
+func (engine *Engine) Dialect() core.Dialect {
+ return engine.dialect
+}
+
// New a session
func (engine *Engine) NewSession() *Session {
session := &Session{Engine: engine}
diff --git a/examples/cachegoroutine.go b/examples/cachegoroutine.go
index 925a16ca..0e50f5ad 100644
--- a/examples/cachegoroutine.go
+++ b/examples/cachegoroutine.go
@@ -2,10 +2,12 @@ package main
import (
"fmt"
+ "os"
+ "time"
+
_ "github.com/go-sql-driver/mysql"
"github.com/go-xorm/xorm"
_ "github.com/mattn/go-sqlite3"
- "os"
)
type User struct {
@@ -84,7 +86,7 @@ func main() {
return
}
engine.ShowSQL = true
- cacher := xorm.NewLRUCacher(xorm.NewMemoryStore(), 1000)
+ cacher := xorm.NewLRUCacher2(xorm.NewMemoryStore(), time.Hour, 1000)
engine.SetDefaultCacher(cacher)
fmt.Println(engine)
test(engine)
@@ -94,7 +96,7 @@ func main() {
fmt.Println("-----start mysql go routines-----")
engine, err = mysqlEngine()
engine.ShowSQL = true
- cacher = xorm.NewLRUCacher(xorm.NewMemoryStore(), 1000)
+ cacher = xorm.NewLRUCacher2(xorm.NewMemoryStore(), time.Hour, 1000)
engine.SetDefaultCacher(cacher)
if err != nil {
fmt.Println(err)
diff --git a/examples/maxconnect.go b/examples/maxconnect.go
index 6bb7c401..5f239d1e 100644
--- a/examples/maxconnect.go
+++ b/examples/maxconnect.go
@@ -34,7 +34,8 @@ func test(engine *xorm.Engine) {
}
engine.ShowSQL = true
- engine.SetMaxConns(5)
+ engine.SetMaxOpenConns(5)
+
size := 1000
queue := make(chan int, size)
diff --git a/examples/sync.go b/examples/sync.go
index f26026aa..ad28ad80 100644
--- a/examples/sync.go
+++ b/examples/sync.go
@@ -2,9 +2,10 @@ package main
import (
"fmt"
- _ "github.com/bylevel/pq"
+
_ "github.com/go-sql-driver/mysql"
"github.com/go-xorm/xorm"
+ _ "github.com/lib/pq"
_ "github.com/mattn/go-sqlite3"
)
diff --git a/session.go b/session.go
index 59ec4eb2..f9204b44 100644
--- a/session.go
+++ b/session.go
@@ -1351,10 +1351,10 @@ func (session *Session) addIndex(tableName, idxName string) error {
if session.IsAutoClose {
defer session.Close()
}
- //fmt.Println(idxName)
- cols := session.Statement.RefTable.Indexes[idxName].Cols
- sqlStr, args := session.Statement.genAddIndexStr(indexName(tableName, idxName), cols)
- _, err = session.exec(sqlStr, args...)
+ index := session.Statement.RefTable.Indexes[idxName]
+ sqlStr := session.Engine.dialect.CreateIndexSql(tableName, index)
+ //genAddIndexStr(indexName(tableName, idxName), cols)
+ _, err = session.exec(sqlStr)
return err
}
@@ -1368,9 +1368,9 @@ func (session *Session) addUnique(tableName, uqeName string) error {
defer session.Close()
}
//fmt.Println(uqeName, session.Statement.RefTable.Uniques)
- cols := session.Statement.RefTable.Indexes[uqeName].Cols
- sqlStr, args := session.Statement.genAddUniqueStr(uniqueName(tableName, uqeName), cols)
- _, err = session.exec(sqlStr, args...)
+ index := session.Statement.RefTable.Indexes[uqeName]
+ sqlStr := session.Engine.dialect.CreateIndexSql(tableName, index)
+ _, err = session.exec(sqlStr)
return err
}
diff --git a/statement.go b/statement.go
index d5704266..3d3e174b 100644
--- a/statement.go
+++ b/statement.go
@@ -99,7 +99,8 @@ func (statement *Statement) Where(querystring string, args ...interface{}) *Stat
// add Where & and statment
func (statement *Statement) And(querystring string, args ...interface{}) *Statement {
if statement.WhereStr != "" {
- statement.WhereStr = fmt.Sprintf("(%v) AND (%v)", statement.WhereStr, querystring)
+ statement.WhereStr = fmt.Sprintf("(%v) %s (%v)", statement.WhereStr,
+ statement.Engine.dialect.AndStr(), querystring)
} else {
statement.WhereStr = querystring
}
@@ -110,7 +111,8 @@ func (statement *Statement) And(querystring string, args ...interface{}) *Statem
// add Where & Or statment
func (statement *Statement) Or(querystring string, args ...interface{}) *Statement {
if statement.WhereStr != "" {
- statement.WhereStr = fmt.Sprintf("(%v) OR (%v)", statement.WhereStr, querystring)
+ statement.WhereStr = fmt.Sprintf("(%v) %s (%v)", statement.WhereStr,
+ statement.Engine.dialect.OrStr(), querystring)
} else {
statement.WhereStr = querystring
}
@@ -442,24 +444,10 @@ func (statement *Statement) Id(id interface{}) *Statement {
statement.IdParam = &pk
}
default:
- // TODO treat as int primitve for now, need to handle type check
+ // TODO: treat as int primitve for now, need to handle type check?
statement.IdParam = &core.PK{id}
-
- // !nashtsai! REVIEW although it will be user's mistake if called Id() twice with
- // different value and Id should be PK's field name, however, at this stage probably
- // can't tell which table is gonna be used
- // if statement.WhereStr == "" {
- // statement.WhereStr = "(id)=?"
- // statement.Params = []interface{}{id}
- // } else {
- // // TODO what if id param has already passed
- // statement.WhereStr = statement.WhereStr + " AND (id)=?"
- // statement.Params = append(statement.Params, id)
- // }
}
- // !nashtsai! perhaps no need to validate pk values' type just let sql complaint happen
-
return statement
}
@@ -507,14 +495,14 @@ func (statement *Statement) genInSql() (string, []interface{}) {
if len(statement.inColumns) == 1 {
return inStrs[0], args
}
- return fmt.Sprintf("(%v)", strings.Join(inStrs, " AND ")), args
+ return fmt.Sprintf("(%v)", strings.Join(inStrs, " "+statement.Engine.dialect.AndStr()+" ")), args
}
func (statement *Statement) attachInSql() {
inSql, inArgs := statement.genInSql()
if len(inSql) > 0 {
if statement.ConditionStr != "" {
- statement.ConditionStr += " AND "
+ statement.ConditionStr += " " + statement.Engine.dialect.AndStr() + " "
}
statement.ConditionStr += inSql
statement.Params = append(statement.Params, inArgs...)
@@ -687,11 +675,9 @@ func uniqueName(tableName, uqeName string) string {
func (s *Statement) genUniqueSQL() []string {
var sqls []string = make([]string, 0)
tbName := s.TableName()
- quote := s.Engine.Quote
- for idxName, unique := range s.RefTable.Indexes {
- if unique.Type == core.UniqueType {
- sql := fmt.Sprintf("CREATE UNIQUE INDEX %v ON %v (%v);", quote(uniqueName(tbName, idxName)),
- quote(tbName), quote(strings.Join(unique.Cols, quote(","))))
+ for _, index := range s.RefTable.Indexes {
+ if index.Type == core.UniqueType {
+ sql := s.Engine.dialect.CreateIndexSql(tbName, index)
sqls = append(sqls, sql)
}
}
@@ -728,7 +714,7 @@ func (statement *Statement) genGetSql(bean interface{}) (string, []interface{})
false, true, statement.allUseBool, statement.useAllCols,
statement.mustColumnMap)
- statement.ConditionStr = strings.Join(colNames, " AND ")
+ statement.ConditionStr = strings.Join(colNames, " "+statement.Engine.dialect.AndStr()+" ")
statement.BeanArgs = args
var columnStr string = statement.ColumnStr
@@ -746,7 +732,7 @@ func (s *Statement) genAddColumnStr(col *core.Column) (string, []interface{}) {
return sql, []interface{}{}
}
-func (s *Statement) genAddIndexStr(idxName string, cols []string) (string, []interface{}) {
+/*func (s *Statement) genAddIndexStr(idxName string, cols []string) (string, []interface{}) {
quote := s.Engine.Quote
colstr := quote(strings.Join(cols, quote(", ")))
sql := fmt.Sprintf("CREATE INDEX %v ON %v (%v);", quote(idxName), quote(s.TableName()), colstr)
@@ -758,7 +744,7 @@ func (s *Statement) genAddUniqueStr(uqeName string, cols []string) (string, []in
colstr := quote(strings.Join(cols, quote(", ")))
sql := fmt.Sprintf("CREATE UNIQUE INDEX %v ON %v (%v);", quote(uqeName), quote(s.TableName()), colstr)
return sql, []interface{}{}
-}
+}*/
func (statement *Statement) genCountSql(bean interface{}) (string, []interface{}) {
table := statement.Engine.autoMap(bean)