add Sync() method for sync column, index to table
This commit is contained in:
parent
4cdec08cc9
commit
7ebd533407
|
@ -42,7 +42,7 @@ type Userdetail struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func directCreateTable(engine *Engine, t *testing.T) {
|
func directCreateTable(engine *Engine, t *testing.T) {
|
||||||
err := engine.CreateTables(&Userinfo{})
|
err := engine.Sync(&Userinfo{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
panic(err)
|
panic(err)
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
package xorm
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
type BigStruct struct {
|
||||||
|
Id int64
|
||||||
|
Name string
|
||||||
|
Title string
|
||||||
|
Age string
|
||||||
|
Alias string
|
||||||
|
NickName string
|
||||||
|
}
|
||||||
|
|
||||||
|
func doBenchCacheFind(engine *Engine, b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
bs := &BigStruct{0, "fafdasf", "fadfa", "afadfsaf", "fadfafdsafd", "fadfafdsaf"}
|
||||||
|
err := engine.CreateTables(bs)
|
||||||
|
if err != nil {
|
||||||
|
b.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < 100; i++ {
|
||||||
|
bs.Id = 0
|
||||||
|
_, err = engine.Insert(bs)
|
||||||
|
if err != nil {
|
||||||
|
b.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
bss := new([]BigStruct)
|
||||||
|
err = engine.Limit(50).Find(bss)
|
||||||
|
if err != nil {
|
||||||
|
b.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.StopTimer()
|
||||||
|
err = engine.DropTables(bs)
|
||||||
|
if err != nil {
|
||||||
|
b.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
132
engine.go
132
engine.go
|
@ -2,6 +2,7 @@ package xorm
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
@ -18,6 +19,7 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
type dialect interface {
|
type dialect interface {
|
||||||
|
Init(uri string) error
|
||||||
SqlType(t *Column) string
|
SqlType(t *Column) string
|
||||||
SupportInsertMany() bool
|
SupportInsertMany() bool
|
||||||
QuoteStr() string
|
QuoteStr() string
|
||||||
|
@ -25,6 +27,9 @@ type dialect interface {
|
||||||
SupportEngine() bool
|
SupportEngine() bool
|
||||||
SupportCharset() bool
|
SupportCharset() bool
|
||||||
IndexOnTable() bool
|
IndexOnTable() bool
|
||||||
|
IndexCheckSql(tableName, idxName string) (string, []interface{})
|
||||||
|
TableCheckSql(tableName string) (string, []interface{})
|
||||||
|
ColumnCheckSql(tableName, colName string) (string, []interface{})
|
||||||
}
|
}
|
||||||
|
|
||||||
type Engine struct {
|
type Engine struct {
|
||||||
|
@ -70,6 +75,7 @@ func (engine *Engine) SetPool(pool IConnectPool) error {
|
||||||
return engine.Pool.Init(engine)
|
return engine.Pool.Init(engine)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// only for go 1.2+
|
||||||
func (engine *Engine) SetMaxConns(conns int) {
|
func (engine *Engine) SetMaxConns(conns int) {
|
||||||
engine.Pool.SetMaxConns(conns)
|
engine.Pool.SetMaxConns(conns)
|
||||||
}
|
}
|
||||||
|
@ -465,6 +471,132 @@ func (engine *Engine) Map(beans ...interface{}) (e error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// is a table has
|
||||||
|
func (engine *Engine) IsEmptyTable(bean interface{}) (bool, error) {
|
||||||
|
t := Type(bean)
|
||||||
|
if t.Kind() != reflect.Struct {
|
||||||
|
return false, errors.New("bean should be a struct or struct's point")
|
||||||
|
}
|
||||||
|
engine.AutoMapType(t)
|
||||||
|
session := engine.NewSession()
|
||||||
|
defer session.Close()
|
||||||
|
has, err := session.Get(bean)
|
||||||
|
return !has, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (engine *Engine) isTableExist(bean interface{}) (bool, error) {
|
||||||
|
t := Type(bean)
|
||||||
|
if t.Kind() != reflect.Struct {
|
||||||
|
return false, errors.New("bean should be a struct or struct's point")
|
||||||
|
}
|
||||||
|
table := engine.AutoMapType(t)
|
||||||
|
session := engine.NewSession()
|
||||||
|
defer session.Close()
|
||||||
|
has, err := session.isTableExist(table.Name)
|
||||||
|
return has, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (engine *Engine) ClearCache(beans ...interface{}) {
|
||||||
|
for _, bean := range beans {
|
||||||
|
table := engine.AutoMap(bean)
|
||||||
|
table.Cacher.ClearIds(table.Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// sync the new struct to database, this method will auto add column, index, unique
|
||||||
|
// but will not delete or change anything.
|
||||||
|
func (engine *Engine) Sync(beans ...interface{}) error {
|
||||||
|
for _, bean := range beans {
|
||||||
|
table := engine.AutoMap(bean)
|
||||||
|
|
||||||
|
s := engine.NewSession()
|
||||||
|
defer s.Close()
|
||||||
|
isExist, err := s.Table(bean).isTableExist(table.Name)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !isExist {
|
||||||
|
err = engine.CreateTables(bean)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
isEmpty, err := engine.IsEmptyTable(bean)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if isEmpty {
|
||||||
|
err = engine.DropTables(bean)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = engine.CreateTables(bean)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for _, col := range table.Columns {
|
||||||
|
session := engine.NewSession()
|
||||||
|
session.Statement.RefTable = table
|
||||||
|
defer session.Close()
|
||||||
|
isExist, err := session.isColumnExist(table.Name, col.Name)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !isExist {
|
||||||
|
session := engine.NewSession()
|
||||||
|
session.Statement.RefTable = table
|
||||||
|
defer session.Close()
|
||||||
|
err = session.addColumn(col.Name)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for idx, _ := range table.Indexes {
|
||||||
|
session := engine.NewSession()
|
||||||
|
session.Statement.RefTable = table
|
||||||
|
defer session.Close()
|
||||||
|
isExist, err := session.isIndexExist(table.Name, idx, false)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !isExist {
|
||||||
|
session := engine.NewSession()
|
||||||
|
session.Statement.RefTable = table
|
||||||
|
defer session.Close()
|
||||||
|
err = session.addIndex(table.Name, idx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for uqe, _ := range table.Uniques {
|
||||||
|
session := engine.NewSession()
|
||||||
|
session.Statement.RefTable = table
|
||||||
|
defer session.Close()
|
||||||
|
isExist, err := session.isIndexExist(table.Name, uqe, true)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !isExist {
|
||||||
|
session := engine.NewSession()
|
||||||
|
session.Statement.RefTable = table
|
||||||
|
defer session.Close()
|
||||||
|
err = session.addUnique(table.Name, uqe)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (engine *Engine) UnMap(beans ...interface{}) (e error) {
|
func (engine *Engine) UnMap(beans ...interface{}) (e error) {
|
||||||
engine.mutex.Lock()
|
engine.mutex.Lock()
|
||||||
defer engine.mutex.Unlock()
|
defer engine.mutex.Unlock()
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
_ "github.com/bylevel/pq"
|
||||||
|
_ "github.com/go-sql-driver/mysql"
|
||||||
|
_ "github.com/mattn/go-sqlite3"
|
||||||
|
"xorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SyncUser struct {
|
||||||
|
Id int64
|
||||||
|
Name string `xorm:"unique"`
|
||||||
|
Age int `xorm:"index"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type SyncLoginInfo struct {
|
||||||
|
Id int64
|
||||||
|
IP string `xorm:"index"`
|
||||||
|
UserId int64
|
||||||
|
AddedCol int
|
||||||
|
// timestamp should be updated by database, so only allow get from db
|
||||||
|
TimeStamp string
|
||||||
|
// assume
|
||||||
|
Nonuse int
|
||||||
|
}
|
||||||
|
|
||||||
|
func sync(engine *xorm.Engine) error {
|
||||||
|
return engine.Sync(&SyncLoginInfo{}, &SyncUser{})
|
||||||
|
}
|
||||||
|
|
||||||
|
func sqliteEngine() (*xorm.Engine, error) {
|
||||||
|
f := "sync.db"
|
||||||
|
//os.Remove(f)
|
||||||
|
|
||||||
|
return xorm.NewEngine("sqlite3", f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func mysqlEngine() (*xorm.Engine, error) {
|
||||||
|
return xorm.NewEngine("mysql", "root:@/test?charset=utf8")
|
||||||
|
}
|
||||||
|
|
||||||
|
func postgresEngine() (*xorm.Engine, error) {
|
||||||
|
return xorm.NewEngine("postgres", "dbname=xorm_test sslmode=disable")
|
||||||
|
}
|
||||||
|
|
||||||
|
type engineFunc func() (*xorm.Engine, error)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
engines := []engineFunc{sqliteEngine, mysqlEngine, postgresEngine}
|
||||||
|
for _, enginefunc := range engines {
|
||||||
|
Orm, err := enginefunc()
|
||||||
|
fmt.Println("--------", Orm.DriverName, "----------")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
Orm.ShowSQL = true
|
||||||
|
err = sync(Orm)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -25,10 +25,10 @@ func (s *PgSeqFilter) Do(sql string, session *Session) string {
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
type PgQuoteFilter struct {
|
type QuoteFilter struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *PgQuoteFilter) Do(sql string, session *Session) string {
|
func (s *QuoteFilter) Do(sql string, session *Session) string {
|
||||||
return strings.Replace(sql, "`", session.Engine.QuoteStr(), -1)
|
return strings.Replace(sql, "`", session.Engine.QuoteStr(), -1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
package xorm
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type mymysql struct {
|
||||||
|
mysql
|
||||||
|
proto string
|
||||||
|
raddr string
|
||||||
|
laddr string
|
||||||
|
timeout time.Duration
|
||||||
|
db string
|
||||||
|
user string
|
||||||
|
passwd string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *mymysql) Init(uri string) error {
|
||||||
|
pd := strings.SplitN(uri, "*", 2)
|
||||||
|
if len(pd) == 2 {
|
||||||
|
// Parse protocol part of URI
|
||||||
|
p := strings.SplitN(pd[0], ":", 2)
|
||||||
|
if len(p) != 2 {
|
||||||
|
return errors.New("Wrong protocol part of URI")
|
||||||
|
}
|
||||||
|
db.proto = p[0]
|
||||||
|
options := strings.Split(p[1], ",")
|
||||||
|
db.raddr = options[0]
|
||||||
|
for _, o := range options[1:] {
|
||||||
|
kv := strings.SplitN(o, "=", 2)
|
||||||
|
var k, v string
|
||||||
|
if len(kv) == 2 {
|
||||||
|
k, v = kv[0], kv[1]
|
||||||
|
} else {
|
||||||
|
k, v = o, "true"
|
||||||
|
}
|
||||||
|
switch k {
|
||||||
|
case "laddr":
|
||||||
|
db.laddr = v
|
||||||
|
case "timeout":
|
||||||
|
to, err := time.ParseDuration(v)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
db.timeout = to
|
||||||
|
default:
|
||||||
|
return errors.New("Unknown option: " + k)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Remove protocol part
|
||||||
|
pd = pd[1:]
|
||||||
|
}
|
||||||
|
// Parse database part of URI
|
||||||
|
dup := strings.SplitN(pd[0], "/", 3)
|
||||||
|
if len(dup) != 3 {
|
||||||
|
return errors.New("Wrong database part of URI")
|
||||||
|
}
|
||||||
|
db.dbname = dup[0]
|
||||||
|
db.user = dup[1]
|
||||||
|
db.passwd = dup[2]
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -10,6 +10,8 @@ CREATE DATABASE IF NOT EXISTS xorm_test CHARACTER SET
|
||||||
utf8 COLLATE utf8_general_ci;
|
utf8 COLLATE utf8_general_ci;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
var showTestSql bool = false
|
||||||
|
|
||||||
func TestMyMysql(t *testing.T) {
|
func TestMyMysql(t *testing.T) {
|
||||||
engine, err := NewEngine("mymysql", "xorm_test2/root/")
|
engine, err := NewEngine("mymysql", "xorm_test2/root/")
|
||||||
defer engine.Close()
|
defer engine.Close()
|
||||||
|
@ -17,8 +19,30 @@ func TestMyMysql(t *testing.T) {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
engine.ShowSQL = true
|
engine.ShowSQL = showTestSql
|
||||||
|
|
||||||
testAll(engine, t)
|
testAll(engine, t)
|
||||||
testAll2(engine, t)
|
testAll2(engine, t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func BenchmarkMyMysqlNoCache(t *testing.B) {
|
||||||
|
engine, err := NewEngine("mymysql", "xorm_test2/root/")
|
||||||
|
defer engine.Close()
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
//engine.ShowSQL = true
|
||||||
|
doBenchCacheFind(engine, t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkMyMysqlCache(t *testing.B) {
|
||||||
|
engine, err := NewEngine("mymysql", "xorm_test2/root/")
|
||||||
|
defer engine.Close()
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
engine.SetDefaultCacher(NewLRUCacher(NewMemoryStore(), 1000))
|
||||||
|
doBenchCacheFind(engine, t)
|
||||||
|
}
|
||||||
|
|
80
mysql.go
80
mysql.go
|
@ -1,10 +1,63 @@
|
||||||
package xorm
|
package xorm
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/tls"
|
||||||
|
//"fmt"
|
||||||
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
//"strings"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type mysql struct {
|
type mysql struct {
|
||||||
|
user string
|
||||||
|
passwd string
|
||||||
|
net string
|
||||||
|
addr string
|
||||||
|
dbname string
|
||||||
|
params map[string]string
|
||||||
|
loc *time.Location
|
||||||
|
timeout time.Duration
|
||||||
|
tls *tls.Config
|
||||||
|
allowAllFiles bool
|
||||||
|
allowOldPasswords bool
|
||||||
|
clientFoundRows bool
|
||||||
|
}
|
||||||
|
|
||||||
|
/*func readBool(input string) (value bool, valid bool) {
|
||||||
|
switch input {
|
||||||
|
case "1", "true", "TRUE", "True":
|
||||||
|
return true, true
|
||||||
|
case "0", "false", "FALSE", "False":
|
||||||
|
return false, true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not a valid bool value
|
||||||
|
return
|
||||||
|
}*/
|
||||||
|
|
||||||
|
func (cfg *mysql) parseDSN(dsn string) (err error) {
|
||||||
|
//cfg.params = make(map[string]string)
|
||||||
|
dsnPattern := regexp.MustCompile(
|
||||||
|
`^(?:(?P<user>.*?)(?::(?P<passwd>.*))?@)?` + // [user[:password]@]
|
||||||
|
`(?:(?P<net>[^\(]*)(?:\((?P<addr>[^\)]*)\))?)?` + // [net[(addr)]]
|
||||||
|
`\/(?P<dbname>.*?)` + // /dbname
|
||||||
|
`(?:\?(?P<params>[^\?]*))?$`) // [?param1=value1¶mN=valueN]
|
||||||
|
matches := dsnPattern.FindStringSubmatch(dsn)
|
||||||
|
//tlsConfigRegister := make(map[string]*tls.Config)
|
||||||
|
names := dsnPattern.SubexpNames()
|
||||||
|
|
||||||
|
for i, match := range matches {
|
||||||
|
switch names[i] {
|
||||||
|
case "dbname":
|
||||||
|
cfg.dbname = match
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *mysql) Init(uri string) error {
|
||||||
|
return db.parseDSN(uri)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *mysql) SqlType(c *Column) string {
|
func (db *mysql) SqlType(c *Column) string {
|
||||||
|
@ -46,14 +99,14 @@ func (db *mysql) QuoteStr() string {
|
||||||
return "`"
|
return "`"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *mysql) AutoIncrStr() string {
|
|
||||||
return "AUTO_INCREMENT"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (db *mysql) SupportEngine() bool {
|
func (db *mysql) SupportEngine() bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (db *mysql) AutoIncrStr() string {
|
||||||
|
return "AUTO_INCREMENT"
|
||||||
|
}
|
||||||
|
|
||||||
func (db *mysql) SupportCharset() bool {
|
func (db *mysql) SupportCharset() bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -61,3 +114,22 @@ func (db *mysql) SupportCharset() bool {
|
||||||
func (db *mysql) IndexOnTable() bool {
|
func (db *mysql) IndexOnTable() bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (db *mysql) IndexCheckSql(tableName, idxName string) (string, []interface{}) {
|
||||||
|
args := []interface{}{db.dbname, tableName, idxName}
|
||||||
|
sql := "SELECT `INDEX_NAME` FROM `INFORMATION_SCHEMA`.`STATISTICS`"
|
||||||
|
sql += " WHERE `TABLE_SCHEMA` = ? AND `TABLE_NAME` = ? AND `INDEX_NAME`=?"
|
||||||
|
return sql, args
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *mysql) ColumnCheckSql(tableName, colName string) (string, []interface{}) {
|
||||||
|
args := []interface{}{db.dbname, tableName, colName}
|
||||||
|
sql := "SELECT `COLUMN_NAME` FROM `INFORMATION_SCHEMA`.`COLUMNS` WHERE `TABLE_SCHEMA` = ? AND `TABLE_NAME` = ? AND `COLUMN_NAME` = ?"
|
||||||
|
return sql, args
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *mysql) TableCheckSql(tableName string) (string, []interface{}) {
|
||||||
|
args := []interface{}{db.dbname, tableName}
|
||||||
|
sql := "SELECT `TABLE_NAME` from `INFORMATION_SCHEMA`.`TABLES` WHERE `TABLE_SCHEMA`=? and `TABLE_NAME`=?"
|
||||||
|
return sql, args
|
||||||
|
}
|
||||||
|
|
|
@ -17,8 +17,30 @@ func TestMysql(t *testing.T) {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
engine.ShowSQL = true
|
engine.ShowSQL = showTestSql
|
||||||
|
|
||||||
testAll(engine, t)
|
testAll(engine, t)
|
||||||
testAll2(engine, t)
|
testAll2(engine, t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func BenchmarkMysqlNoCache(t *testing.B) {
|
||||||
|
engine, err := NewEngine("mysql", "root:@/xorm_test?charset=utf8")
|
||||||
|
defer engine.Close()
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
//engine.ShowSQL = true
|
||||||
|
doBenchCacheFind(engine, t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkMysqlCache(t *testing.B) {
|
||||||
|
engine, err := NewEngine("mysql", "root:@/xorm_test?charset=utf8")
|
||||||
|
defer engine.Close()
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
engine.SetDefaultCacher(NewLRUCacher(NewMemoryStore(), 1000))
|
||||||
|
doBenchCacheFind(engine, t)
|
||||||
|
}
|
||||||
|
|
69
postgres.go
69
postgres.go
|
@ -1,8 +1,58 @@
|
||||||
package xorm
|
package xorm
|
||||||
|
|
||||||
import "strconv"
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
type postgres struct {
|
type postgres struct {
|
||||||
|
dbname string
|
||||||
|
}
|
||||||
|
|
||||||
|
type Values map[string]string
|
||||||
|
|
||||||
|
func (vs Values) Set(k, v string) {
|
||||||
|
vs[k] = v
|
||||||
|
}
|
||||||
|
|
||||||
|
func (vs Values) Get(k string) (v string) {
|
||||||
|
return vs[k]
|
||||||
|
}
|
||||||
|
|
||||||
|
type Error error
|
||||||
|
|
||||||
|
func errorf(s string, args ...interface{}) {
|
||||||
|
panic(Error(fmt.Errorf("pq: %s", fmt.Sprintf(s, args...))))
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseOpts(name string, o Values) {
|
||||||
|
if len(name) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
name = strings.TrimSpace(name)
|
||||||
|
|
||||||
|
ps := strings.Split(name, " ")
|
||||||
|
for _, p := range ps {
|
||||||
|
kv := strings.Split(p, "=")
|
||||||
|
if len(kv) < 2 {
|
||||||
|
errorf("invalid option: %q", p)
|
||||||
|
}
|
||||||
|
o.Set(kv[0], kv[1])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *postgres) Init(uri string) error {
|
||||||
|
o := make(Values)
|
||||||
|
parseOpts(uri, o)
|
||||||
|
|
||||||
|
db.dbname = o.Get("dbname")
|
||||||
|
if db.dbname == "" {
|
||||||
|
return errors.New("dbname is empty")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *postgres) SqlType(c *Column) string {
|
func (db *postgres) SqlType(c *Column) string {
|
||||||
|
@ -68,3 +118,20 @@ func (db *postgres) SupportCharset() bool {
|
||||||
func (db *postgres) IndexOnTable() bool {
|
func (db *postgres) IndexOnTable() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (db *postgres) IndexCheckSql(tableName, idxName string) (string, []interface{}) {
|
||||||
|
args := []interface{}{tableName, idxName}
|
||||||
|
return `SELECT indexname FROM pg_indexes ` +
|
||||||
|
`WHERE tablename = ? AND indexname = ?`, args
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *postgres) TableCheckSql(tableName string) (string, []interface{}) {
|
||||||
|
args := []interface{}{tableName}
|
||||||
|
return `SELECT tablename FROM pg_tables WHERE tablename = ?`, args
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *postgres) ColumnCheckSql(tableName, colName string) (string, []interface{}) {
|
||||||
|
args := []interface{}{tableName, colName}
|
||||||
|
return "SELECT column_name FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = ?" +
|
||||||
|
" AND column_name = ?", args
|
||||||
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ func TestPostgres(t *testing.T) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer engine.Close()
|
defer engine.Close()
|
||||||
engine.ShowSQL = true
|
engine.ShowSQL = showTestSql
|
||||||
|
|
||||||
testAll(engine, t)
|
testAll(engine, t)
|
||||||
testAll2(engine, t)
|
testAll2(engine, t)
|
||||||
|
@ -26,7 +26,7 @@ func TestPostgres2(t *testing.T) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer engine.Close()
|
defer engine.Close()
|
||||||
engine.ShowSQL = true
|
engine.ShowSQL = showTestSql
|
||||||
engine.Mapper = SameMapper{}
|
engine.Mapper = SameMapper{}
|
||||||
|
|
||||||
fmt.Println("-------------- directCreateTable --------------")
|
fmt.Println("-------------- directCreateTable --------------")
|
||||||
|
@ -98,3 +98,27 @@ func TestPostgres2(t *testing.T) {
|
||||||
fmt.Println("-------------- testIndexAndUnique --------------")
|
fmt.Println("-------------- testIndexAndUnique --------------")
|
||||||
testIndexAndUnique(engine, t)
|
testIndexAndUnique(engine, t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func BenchmarkPostgresNoCache(t *testing.B) {
|
||||||
|
engine, err := NewEngine("postgres", "dbname=xorm_test sslmode=disable")
|
||||||
|
|
||||||
|
defer engine.Close()
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
//engine.ShowSQL = true
|
||||||
|
doBenchCacheFind(engine, t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkPostgresCache(t *testing.B) {
|
||||||
|
engine, err := NewEngine("postgres", "dbname=xorm_test sslmode=disable")
|
||||||
|
|
||||||
|
defer engine.Close()
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
engine.SetDefaultCacher(NewLRUCacher(NewMemoryStore(), 1000))
|
||||||
|
doBenchCacheFind(engine, t)
|
||||||
|
}
|
||||||
|
|
163
session.go
163
session.go
|
@ -293,10 +293,18 @@ func (session *Session) CreateTable(bean interface{}) error {
|
||||||
return session.createOneTable()
|
return session.createOneTable()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (session *Session) createOneTable() error {
|
func (session *Session) CreateIndexes(bean interface{}) error {
|
||||||
sql := session.Statement.genCreateSQL()
|
session.Statement.RefTable = session.Engine.AutoMap(bean)
|
||||||
_, err := session.exec(sql)
|
|
||||||
if err == nil {
|
err := session.newDb()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer session.Statement.Init()
|
||||||
|
if session.IsAutoClose {
|
||||||
|
defer session.Close()
|
||||||
|
}
|
||||||
|
|
||||||
sqls := session.Statement.genIndexSQL()
|
sqls := session.Statement.genIndexSQL()
|
||||||
for _, sql := range sqls {
|
for _, sql := range sqls {
|
||||||
_, err = session.exec(sql)
|
_, err = session.exec(sql)
|
||||||
|
@ -304,8 +312,21 @@ func (session *Session) createOneTable() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (session *Session) CreateUniques(bean interface{}) error {
|
||||||
|
session.Statement.RefTable = session.Engine.AutoMap(bean)
|
||||||
|
|
||||||
|
err := session.newDb()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
if err == nil {
|
defer session.Statement.Init()
|
||||||
|
if session.IsAutoClose {
|
||||||
|
defer session.Close()
|
||||||
|
}
|
||||||
|
|
||||||
sqls := session.Statement.genUniqueSQL()
|
sqls := session.Statement.genUniqueSQL()
|
||||||
for _, sql := range sqls {
|
for _, sql := range sqls {
|
||||||
_, err = session.exec(sql)
|
_, err = session.exec(sql)
|
||||||
|
@ -313,7 +334,12 @@ func (session *Session) createOneTable() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (session *Session) createOneTable() error {
|
||||||
|
sql := session.Statement.genCreateSQL()
|
||||||
|
_, err := session.exec(sql)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -337,6 +363,26 @@ func (session *Session) CreateAll() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (session *Session) DropIndexes(bean interface{}) error {
|
||||||
|
err := session.newDb()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer session.Statement.Init()
|
||||||
|
if session.IsAutoClose {
|
||||||
|
defer session.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
sqls := session.Statement.genDelIndexSQL()
|
||||||
|
for _, sql := range sqls {
|
||||||
|
_, err = session.exec(sql)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// DropTable drop a table and all indexes of the table
|
// DropTable drop a table and all indexes of the table
|
||||||
func (session *Session) DropTable(bean interface{}) error {
|
func (session *Session) DropTable(bean interface{}) error {
|
||||||
err := session.newDb()
|
err := session.newDb()
|
||||||
|
@ -355,14 +401,6 @@ func (session *Session) DropTable(bean interface{}) error {
|
||||||
session.Statement.AltTableName = bean.(string)
|
session.Statement.AltTableName = bean.(string)
|
||||||
} else if t.Kind() == reflect.Struct {
|
} else if t.Kind() == reflect.Struct {
|
||||||
session.Statement.RefTable = session.Engine.AutoMap(bean)
|
session.Statement.RefTable = session.Engine.AutoMap(bean)
|
||||||
|
|
||||||
sqls := session.Statement.genDelIndexSQL()
|
|
||||||
for _, sql := range sqls {
|
|
||||||
_, err = session.exec(sql)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
return errors.New("Unsupported type")
|
return errors.New("Unsupported type")
|
||||||
}
|
}
|
||||||
|
@ -727,6 +765,7 @@ func (session *Session) Find(rowsSlicePtr interface{}, condiBean ...interface{})
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// test if database is ok
|
||||||
func (session *Session) Ping() error {
|
func (session *Session) Ping() error {
|
||||||
err := session.newDb()
|
err := session.newDb()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -740,6 +779,102 @@ func (session *Session) Ping() error {
|
||||||
return session.Db.Ping()
|
return session.Db.Ping()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (session *Session) isColumnExist(tableName, colName string) (bool, error) {
|
||||||
|
err := session.newDb()
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
defer session.Statement.Init()
|
||||||
|
if session.IsAutoClose {
|
||||||
|
defer session.Close()
|
||||||
|
}
|
||||||
|
sql, args := session.Engine.Dialect.ColumnCheckSql(tableName, colName)
|
||||||
|
results, err := session.query(sql, args...)
|
||||||
|
return len(results) > 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (session *Session) isTableExist(tableName string) (bool, error) {
|
||||||
|
err := session.newDb()
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
defer session.Statement.Init()
|
||||||
|
if session.IsAutoClose {
|
||||||
|
defer session.Close()
|
||||||
|
}
|
||||||
|
sql, args := session.Engine.Dialect.TableCheckSql(tableName)
|
||||||
|
results, err := session.query(sql, args...)
|
||||||
|
return len(results) > 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (session *Session) isIndexExist(tableName, idxName string, unique bool) (bool, error) {
|
||||||
|
err := session.newDb()
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
defer session.Statement.Init()
|
||||||
|
if session.IsAutoClose {
|
||||||
|
defer session.Close()
|
||||||
|
}
|
||||||
|
var idx string
|
||||||
|
if unique {
|
||||||
|
idx = uniqueName(tableName, idxName)
|
||||||
|
} else {
|
||||||
|
idx = indexName(tableName, idxName)
|
||||||
|
}
|
||||||
|
sql, args := session.Engine.Dialect.IndexCheckSql(tableName, idx)
|
||||||
|
results, err := session.query(sql, args...)
|
||||||
|
return len(results) > 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (session *Session) addColumn(colName string) error {
|
||||||
|
err := session.newDb()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer session.Statement.Init()
|
||||||
|
if session.IsAutoClose {
|
||||||
|
defer session.Close()
|
||||||
|
}
|
||||||
|
//fmt.Println(session.Statement.RefTable)
|
||||||
|
col := session.Statement.RefTable.Columns[colName]
|
||||||
|
sql, args := session.Statement.genAddColumnStr(col)
|
||||||
|
_, err = session.exec(sql, args...)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (session *Session) addIndex(tableName, idxName string) error {
|
||||||
|
err := session.newDb()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer session.Statement.Init()
|
||||||
|
if session.IsAutoClose {
|
||||||
|
defer session.Close()
|
||||||
|
}
|
||||||
|
//fmt.Println(idxName)
|
||||||
|
cols := session.Statement.RefTable.Indexes[idxName]
|
||||||
|
sql, args := session.Statement.genAddIndexStr(indexName(tableName, idxName), cols)
|
||||||
|
_, err = session.exec(sql, args...)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (session *Session) addUnique(tableName, uqeName string) error {
|
||||||
|
err := session.newDb()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer session.Statement.Init()
|
||||||
|
if session.IsAutoClose {
|
||||||
|
defer session.Close()
|
||||||
|
}
|
||||||
|
//fmt.Println(uqeName, session.Statement.RefTable.Uniques)
|
||||||
|
cols := session.Statement.RefTable.Uniques[uqeName]
|
||||||
|
sql, args := session.Statement.genAddUniqueStr(uniqueName(tableName, uqeName), cols)
|
||||||
|
_, err = session.exec(sql, args...)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
func (session *Session) DropAll() error {
|
func (session *Session) DropAll() error {
|
||||||
err := session.newDb()
|
err := session.newDb()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
19
sqlite3.go
19
sqlite3.go
|
@ -3,6 +3,10 @@ package xorm
|
||||||
type sqlite3 struct {
|
type sqlite3 struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (db *sqlite3) Init(uri string) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (db *sqlite3) SqlType(c *Column) string {
|
func (db *sqlite3) SqlType(c *Column) string {
|
||||||
switch t := c.SQLType.Name; t {
|
switch t := c.SQLType.Name; t {
|
||||||
case Date, DateTime, TimeStamp, Time:
|
case Date, DateTime, TimeStamp, Time:
|
||||||
|
@ -50,3 +54,18 @@ func (db *sqlite3) SupportCharset() bool {
|
||||||
func (db *sqlite3) IndexOnTable() bool {
|
func (db *sqlite3) IndexOnTable() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (db *sqlite3) IndexCheckSql(tableName, idxName string) (string, []interface{}) {
|
||||||
|
args := []interface{}{idxName}
|
||||||
|
return "SELECT name FROM sqlite_master WHERE type='index' and name = ?", args
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *sqlite3) TableCheckSql(tableName string) (string, []interface{}) {
|
||||||
|
args := []interface{}{tableName}
|
||||||
|
return "SELECT name FROM sqlite_master WHERE type='table' and name = ?", args
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *sqlite3) ColumnCheckSql(tableName, colName string) (string, []interface{}) {
|
||||||
|
args := []interface{}{tableName}
|
||||||
|
return "SELECT name FROM sqlite_master WHERE type='table' and name = ? and sql like '%`" + colName + "`%'", args
|
||||||
|
}
|
||||||
|
|
|
@ -14,8 +14,32 @@ func TestSqlite3(t *testing.T) {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
engine.ShowSQL = true
|
engine.ShowSQL = showTestSql
|
||||||
|
|
||||||
testAll(engine, t)
|
testAll(engine, t)
|
||||||
testAll2(engine, t)
|
testAll2(engine, t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func BenchmarkSqlite3NoCache(t *testing.B) {
|
||||||
|
os.Remove("./test.db")
|
||||||
|
engine, err := NewEngine("sqlite3", "./test.db")
|
||||||
|
defer engine.Close()
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
//engine.ShowSQL = true
|
||||||
|
doBenchCacheFind(engine, t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkSqlite3Cache(t *testing.B) {
|
||||||
|
os.Remove("./test.db")
|
||||||
|
engine, err := NewEngine("sqlite3", "./test.db")
|
||||||
|
defer engine.Close()
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
engine.SetDefaultCacher(NewLRUCacher(NewMemoryStore(), 1000))
|
||||||
|
doBenchCacheFind(engine, t)
|
||||||
|
}
|
||||||
|
|
63
statement.go
63
statement.go
|
@ -279,47 +279,57 @@ func (statement *Statement) genCreateSQL() string {
|
||||||
return sql
|
return sql
|
||||||
}
|
}
|
||||||
|
|
||||||
func (statement *Statement) genIndexSQL() []string {
|
func indexName(tableName, idxName string) string {
|
||||||
|
return fmt.Sprintf("IDX_%v_%v", tableName, idxName)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Statement) genIndexSQL() []string {
|
||||||
var sqls []string = make([]string, 0)
|
var sqls []string = make([]string, 0)
|
||||||
for indexName, cols := range statement.RefTable.Indexes {
|
tbName := s.TableName()
|
||||||
sql := fmt.Sprintf("CREATE INDEX IDX_%v_%v ON %v (%v);", statement.TableName(), indexName,
|
quote := s.Engine.Quote
|
||||||
statement.Engine.Quote(statement.TableName()), statement.Engine.Quote(strings.Join(cols, statement.Engine.Quote(","))))
|
for idxName, cols := range s.RefTable.Indexes {
|
||||||
|
sql := fmt.Sprintf("CREATE INDEX %v ON %v (%v);", quote(indexName(tbName, idxName)),
|
||||||
|
quote(tbName), quote(strings.Join(cols, quote(","))))
|
||||||
sqls = append(sqls, sql)
|
sqls = append(sqls, sql)
|
||||||
}
|
}
|
||||||
return sqls
|
return sqls
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func uniqueName(tableName, uqeName string) string {
|
||||||
|
return fmt.Sprintf("UQE_%v_%v", tableName, uqeName)
|
||||||
|
}
|
||||||
|
|
||||||
func (statement *Statement) genUniqueSQL() []string {
|
func (statement *Statement) genUniqueSQL() []string {
|
||||||
var sqls []string = make([]string, 0)
|
var sqls []string = make([]string, 0)
|
||||||
for indexName, cols := range statement.RefTable.Uniques {
|
for indexName, cols := range statement.RefTable.Uniques {
|
||||||
sql := fmt.Sprintf("CREATE UNIQUE INDEX `UQE_%v_%v` ON %v (%v);", statement.TableName(), indexName,
|
sql := fmt.Sprintf("CREATE UNIQUE INDEX `%v` ON %v (%v);", uniqueName(statement.TableName(), indexName),
|
||||||
statement.Engine.Quote(statement.TableName()), statement.Engine.Quote(strings.Join(cols, statement.Engine.Quote(","))))
|
statement.Engine.Quote(statement.TableName()), statement.Engine.Quote(strings.Join(cols, statement.Engine.Quote(","))))
|
||||||
sqls = append(sqls, sql)
|
sqls = append(sqls, sql)
|
||||||
}
|
}
|
||||||
return sqls
|
return sqls
|
||||||
}
|
}
|
||||||
|
|
||||||
func (statement *Statement) genDelIndexSQL() []string {
|
func (s *Statement) genDelIndexSQL() []string {
|
||||||
var sqls []string = make([]string, 0)
|
var sqls []string = make([]string, 0)
|
||||||
for indexName, _ := range statement.RefTable.Uniques {
|
for indexName, _ := range s.RefTable.Uniques {
|
||||||
sql := fmt.Sprintf("DROP INDEX `UQE_%v_%v`", statement.TableName(), indexName)
|
sql := fmt.Sprintf("DROP INDEX %v", s.Engine.Quote(uniqueName(s.TableName(), indexName)))
|
||||||
if statement.Engine.Dialect.IndexOnTable() {
|
if s.Engine.Dialect.IndexOnTable() {
|
||||||
sql += fmt.Sprintf(" ON %v", statement.Engine.Quote(statement.TableName()))
|
sql += fmt.Sprintf(" ON %v", s.Engine.Quote(s.TableName()))
|
||||||
}
|
}
|
||||||
sqls = append(sqls, sql)
|
sqls = append(sqls, sql)
|
||||||
}
|
}
|
||||||
for indexName, _ := range statement.RefTable.Indexes {
|
for indexName, _ := range s.RefTable.Indexes {
|
||||||
sql := fmt.Sprintf("DROP INDEX IDX_%v_%v", statement.TableName(), indexName)
|
sql := fmt.Sprintf("DROP INDEX %v", s.Engine.Quote(uniqueName(s.TableName(), indexName)))
|
||||||
if statement.Engine.Dialect.IndexOnTable() {
|
if s.Engine.Dialect.IndexOnTable() {
|
||||||
sql += fmt.Sprintf(" ON %v", statement.Engine.Quote(statement.TableName()))
|
sql += fmt.Sprintf(" ON %v", s.Engine.Quote(s.TableName()))
|
||||||
}
|
}
|
||||||
sqls = append(sqls, sql)
|
sqls = append(sqls, sql)
|
||||||
}
|
}
|
||||||
return sqls
|
return sqls
|
||||||
}
|
}
|
||||||
|
|
||||||
func (statement *Statement) genDropSQL() string {
|
func (s *Statement) genDropSQL() string {
|
||||||
sql := "DROP TABLE IF EXISTS " + statement.Engine.Quote(statement.TableName()) + ";"
|
sql := "DROP TABLE IF EXISTS " + s.Engine.Quote(s.TableName()) + ";"
|
||||||
return sql
|
return sql
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -339,6 +349,27 @@ func (statement Statement) genGetSql(bean interface{}) (string, []interface{}) {
|
||||||
return statement.genSelectSql(columnStr), append(statement.Params, statement.BeanArgs...)
|
return statement.genSelectSql(columnStr), append(statement.Params, statement.BeanArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Statement) genAddColumnStr(col *Column) (string, []interface{}) {
|
||||||
|
quote := s.Engine.Quote
|
||||||
|
sql := fmt.Sprintf("ALTER TABLE %v ADD COLUMN %v;", quote(s.TableName()),
|
||||||
|
col.String(s.Engine))
|
||||||
|
return sql, []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)
|
||||||
|
return sql, []interface{}{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Statement) genAddUniqueStr(uqeName string, cols []string) (string, []interface{}) {
|
||||||
|
quote := s.Engine.Quote
|
||||||
|
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{}) {
|
func (statement Statement) genCountSql(bean interface{}) (string, []interface{}) {
|
||||||
table := statement.Engine.AutoMap(bean)
|
table := statement.Engine.AutoMap(bean)
|
||||||
statement.RefTable = table
|
statement.RefTable = table
|
||||||
|
|
10
table.go
10
table.go
|
@ -161,6 +161,16 @@ const (
|
||||||
UNIONUNIQUE
|
UNIONUNIQUE
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type Index struct {
|
||||||
|
Name string
|
||||||
|
IsUnique bool
|
||||||
|
Cols []*Column
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewIndex(name string, isUnique bool) *Index {
|
||||||
|
return &Index{name, isUnique, make([]*Column, 0)}
|
||||||
|
}
|
||||||
|
|
||||||
type Column struct {
|
type Column struct {
|
||||||
Name string
|
Name string
|
||||||
FieldName string
|
FieldName string
|
||||||
|
|
27
xorm.go
27
xorm.go
|
@ -17,16 +17,12 @@ func close(engine *Engine) {
|
||||||
engine.Close()
|
engine.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
// new a db manager according to the parameter. Currently support three
|
// new a db manager according to the parameter. Currently support four
|
||||||
// driver
|
// drivers
|
||||||
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{DriverName: driverName, Mapper: SnakeMapper{},
|
||||||
DataSourceName: dataSourceName}
|
DataSourceName: dataSourceName, Filters: make([]Filter, 0)}
|
||||||
|
|
||||||
engine.Tables = make(map[reflect.Type]*Table)
|
|
||||||
engine.mutex = &sync.Mutex{}
|
|
||||||
engine.TagIdentifier = "xorm"
|
|
||||||
engine.Filters = make([]Filter, 0)
|
|
||||||
if driverName == SQLITE {
|
if driverName == SQLITE {
|
||||||
engine.Dialect = &sqlite3{}
|
engine.Dialect = &sqlite3{}
|
||||||
} else if driverName == MYSQL {
|
} else if driverName == MYSQL {
|
||||||
|
@ -34,19 +30,28 @@ func NewEngine(driverName string, dataSourceName string) (*Engine, error) {
|
||||||
} else if driverName == POSTGRES {
|
} else if driverName == POSTGRES {
|
||||||
engine.Dialect = &postgres{}
|
engine.Dialect = &postgres{}
|
||||||
engine.Filters = append(engine.Filters, &PgSeqFilter{})
|
engine.Filters = append(engine.Filters, &PgSeqFilter{})
|
||||||
engine.Filters = append(engine.Filters, &PgQuoteFilter{})
|
engine.Filters = append(engine.Filters, &QuoteFilter{})
|
||||||
} else if driverName == MYMYSQL {
|
} else if driverName == MYMYSQL {
|
||||||
engine.Dialect = &mysql{}
|
engine.Dialect = &mymysql{}
|
||||||
} else {
|
} else {
|
||||||
return nil, errors.New(fmt.Sprintf("Unsupported driver name: %v", driverName))
|
return nil, errors.New(fmt.Sprintf("Unsupported driver name: %v", driverName))
|
||||||
}
|
}
|
||||||
|
err := engine.Dialect.Init(dataSourceName)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
engine.Tables = make(map[reflect.Type]*Table)
|
||||||
|
engine.mutex = &sync.Mutex{}
|
||||||
|
engine.TagIdentifier = "xorm"
|
||||||
|
|
||||||
engine.Filters = append(engine.Filters, &IdFilter{})
|
engine.Filters = append(engine.Filters, &IdFilter{})
|
||||||
engine.Logger = os.Stdout
|
engine.Logger = os.Stdout
|
||||||
|
|
||||||
//engine.Pool = NewSimpleConnectPool()
|
//engine.Pool = NewSimpleConnectPool()
|
||||||
//engine.Pool = NewNoneConnectPool()
|
//engine.Pool = NewNoneConnectPool()
|
||||||
//engine.Cacher = NewLRUCacher()
|
//engine.Cacher = NewLRUCacher()
|
||||||
err := engine.SetPool(NewSysConnectPool())
|
err = engine.SetPool(NewSysConnectPool())
|
||||||
runtime.SetFinalizer(engine, close)
|
runtime.SetFinalizer(engine, close)
|
||||||
return engine, err
|
return engine, err
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue