some fixes with tests and added mssql support

This commit is contained in:
Lunny Xiao 2017-06-02 15:56:46 +08:00
parent 13386a83fa
commit 7ca3a09a80
No known key found for this signature in database
GPG Key ID: C3B7C91B632F738A
14 changed files with 78 additions and 28 deletions

View File

@ -21,7 +21,7 @@ database:
test: test:
override: override:
# './...' is a relative pattern which means all subdirectories # './...' is a relative pattern which means all subdirectories
- go test -v -race -db="sqlite3;mysql;postgres" -conn_str="./test.db;root:@/xorm_test;dbname=xorm_test sslmode=disable" -coverprofile=coverage.txt -covermode=atomic - go test -v -race -db="sqlite3::mysql::postgres" -conn_str="./test.db::root:@/xorm_test::dbname=xorm_test sslmode=disable" -coverprofile=coverage.txt -covermode=atomic
- cd /home/ubuntu/.go_workspace/src/github.com/go-xorm/tests && ./sqlite3.sh - cd /home/ubuntu/.go_workspace/src/github.com/go-xorm/tests && ./sqlite3.sh
- cd /home/ubuntu/.go_workspace/src/github.com/go-xorm/tests && ./mysql.sh - cd /home/ubuntu/.go_workspace/src/github.com/go-xorm/tests && ./mysql.sh
- cd /home/ubuntu/.go_workspace/src/github.com/go-xorm/tests && ./postgres.sh - cd /home/ubuntu/.go_workspace/src/github.com/go-xorm/tests && ./postgres.sh

View File

@ -215,7 +215,7 @@ func (db *mssql) SqlType(c *core.Column) string {
var res string var res string
switch t := c.SQLType.Name; t { switch t := c.SQLType.Name; t {
case core.Bool: case core.Bool:
res = core.TinyInt res = core.Bit
if strings.EqualFold(c.Default, "true") { if strings.EqualFold(c.Default, "true") {
c.Default = "1" c.Default = "1"
} else { } else {
@ -250,6 +250,9 @@ func (db *mssql) SqlType(c *core.Column) string {
case core.Uuid: case core.Uuid:
res = core.Varchar res = core.Varchar
c.Length = 40 c.Length = 40
case core.TinyInt:
res = core.TinyInt
c.Length = 0
default: default:
res = t res = t
} }
@ -335,9 +338,15 @@ func (db *mssql) TableCheckSql(tableName string) (string, []interface{}) {
func (db *mssql) GetColumns(tableName string) ([]string, map[string]*core.Column, error) { func (db *mssql) GetColumns(tableName string) ([]string, map[string]*core.Column, error) {
args := []interface{}{} args := []interface{}{}
s := `select a.name as name, b.name as ctype,a.max_length,a.precision,a.scale,a.is_nullable as nullable, s := `select a.name as name, b.name as ctype,a.max_length,a.precision,a.scale,a.is_nullable as nullable,
replace(replace(isnull(c.text,''),'(',''),')','') as vdefault replace(replace(isnull(c.text,''),'(',''),')','') as vdefault,
from sys.columns a left join sys.types b on a.user_type_id=b.user_type_id ISNULL(i.is_primary_key, 0)
left join sys.syscomments c on a.default_object_id=c.id from sys.columns a
left join sys.types b on a.user_type_id=b.user_type_id
left join sys.syscomments c on a.default_object_id=c.id
LEFT OUTER JOIN
sys.index_columns ic ON ic.object_id = a.object_id AND ic.column_id = a.column_id
LEFT OUTER JOIN
sys.indexes i ON ic.object_id = i.object_id AND ic.index_id = i.index_id
where a.object_id=object_id('` + tableName + `')` where a.object_id=object_id('` + tableName + `')`
db.LogSQL(s, args) db.LogSQL(s, args)
@ -352,8 +361,8 @@ func (db *mssql) GetColumns(tableName string) ([]string, map[string]*core.Column
for rows.Next() { for rows.Next() {
var name, ctype, vdefault string var name, ctype, vdefault string
var maxLen, precision, scale int var maxLen, precision, scale int
var nullable bool var nullable, isPK bool
err = rows.Scan(&name, &ctype, &maxLen, &precision, &scale, &nullable, &vdefault) err = rows.Scan(&name, &ctype, &maxLen, &precision, &scale, &nullable, &vdefault, &isPK)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -363,6 +372,7 @@ func (db *mssql) GetColumns(tableName string) ([]string, map[string]*core.Column
col.Name = strings.Trim(name, "` ") col.Name = strings.Trim(name, "` ")
col.Nullable = nullable col.Nullable = nullable
col.Default = vdefault col.Default = vdefault
col.IsPrimaryKey = isPK
ct := strings.ToUpper(ctype) ct := strings.ToUpper(ctype)
if ct == "DECIMAL" { if ct == "DECIMAL" {
col.Length = precision col.Length = precision
@ -536,7 +546,6 @@ type odbcDriver struct {
func (p *odbcDriver) Parse(driverName, dataSourceName string) (*core.Uri, error) { func (p *odbcDriver) Parse(driverName, dataSourceName string) (*core.Uri, error) {
kv := strings.Split(dataSourceName, ";") kv := strings.Split(dataSourceName, ";")
var dbName string var dbName string
for _, c := range kv { for _, c := range kv {
vv := strings.Split(strings.TrimSpace(c), "=") vv := strings.Split(strings.TrimSpace(c), "=")
if len(vv) == 2 { if len(vv) == 2 {

View File

@ -1512,9 +1512,14 @@ func (engine *Engine) NowTime2(sqlTypeName string) (interface{}, time.Time) {
} }
func (engine *Engine) formatColTime(col *core.Column, t time.Time) (v interface{}) { func (engine *Engine) formatColTime(col *core.Column, t time.Time) (v interface{}) {
if col.DisableTimeZone { if t.IsZero() {
return engine.formatTime(col.SQLType.Name, t) if col.Nullable {
} else if col.TimeZone != nil { return nil
}
return ""
}
if col.TimeZone != nil {
return engine.formatTime(col.SQLType.Name, t.In(col.TimeZone)) return engine.formatTime(col.SQLType.Name, t.In(col.TimeZone))
} }
return engine.formatTime(col.SQLType.Name, t.In(engine.DatabaseTZ)) return engine.formatTime(col.SQLType.Name, t.In(engine.DatabaseTZ))

View File

@ -7,6 +7,7 @@ package xorm
import ( import (
"testing" "testing"
"github.com/go-xorm/core"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
@ -26,7 +27,11 @@ func TestSetExpr(t *testing.T) {
assert.NoError(t, err) assert.NoError(t, err)
assert.EqualValues(t, 1, cnt) assert.EqualValues(t, 1, cnt)
cnt, err = testEngine.SetExpr("show", "NOT `show`").Id(1).Update(new(User)) var not = "NOT"
if testEngine.dialect.DBType() == core.MSSQL {
not = "~"
}
cnt, err = testEngine.SetExpr("show", not+" `show`").Id(1).Update(new(User))
assert.NoError(t, err) assert.NoError(t, err)
assert.EqualValues(t, 1, cnt) assert.EqualValues(t, 1, cnt)
} }

View File

@ -586,11 +586,6 @@ func (session *Session) value2Interface(col *core.Column, fieldValue reflect.Val
case reflect.Struct: case reflect.Struct:
if fieldType.ConvertibleTo(core.TimeType) { if fieldType.ConvertibleTo(core.TimeType) {
t := fieldValue.Convert(core.TimeType).Interface().(time.Time) t := fieldValue.Convert(core.TimeType).Interface().(time.Time)
if session.Engine.dialect.DBType() == core.MSSQL {
if t.IsZero() {
return nil, nil
}
}
tf := session.Engine.formatColTime(col, t) tf := session.Engine.formatColTime(col, t)
return tf, nil return tf, nil
} }

View File

@ -9,6 +9,7 @@ import (
"testing" "testing"
"time" "time"
"github.com/go-xorm/core"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
@ -119,6 +120,11 @@ func TestGetStruct(t *testing.T) {
assert.NoError(t, testEngine.Sync(new(UserinfoGet))) assert.NoError(t, testEngine.Sync(new(UserinfoGet)))
var err error
if testEngine.dialect.DBType() == core.MSSQL {
_, err = testEngine.Exec("SET IDENTITY_INSERT userinfo_get ON")
assert.NoError(t, err)
}
cnt, err := testEngine.Insert(&UserinfoGet{Uid: 2}) cnt, err := testEngine.Insert(&UserinfoGet{Uid: 2})
assert.NoError(t, err) assert.NoError(t, err)
assert.EqualValues(t, 1, cnt) assert.EqualValues(t, 1, cnt)

View File

@ -357,10 +357,10 @@ func (session *Session) innerInsert(bean interface{}) (int64, error) {
session.Engine.QuoteStr(), session.Engine.QuoteStr(),
colPlaces) colPlaces)
} else { } else {
if session.Engine.dialect.DBType() == core.SQLITE || session.Engine.dialect.DBType() == core.POSTGRES { if session.Engine.dialect.DBType() == core.MYSQL {
sqlStr = fmt.Sprintf("INSERT INTO %s DEFAULT VALUES", session.Engine.Quote(session.Statement.TableName()))
} else {
sqlStr = fmt.Sprintf("INSERT INTO %s VALUES ()", session.Engine.Quote(session.Statement.TableName())) sqlStr = fmt.Sprintf("INSERT INTO %s VALUES ()", session.Engine.Quote(session.Statement.TableName()))
} else {
sqlStr = fmt.Sprintf("INSERT INTO %s DEFAULT VALUES", session.Engine.Quote(session.Statement.TableName()))
} }
} }

View File

@ -298,7 +298,19 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6
condSQL = "WHERE " + condSQL condSQL = "WHERE " + condSQL
} }
} else if st.Engine.dialect.DBType() == core.MSSQL { } else if st.Engine.dialect.DBType() == core.MSSQL {
top = fmt.Sprintf("top (%d) ", st.LimitN) if st.OrderStr != "" && st.Engine.dialect.DBType() == core.MSSQL &&
table != nil && len(table.PrimaryKeys) == 1 {
cond = builder.Expr(fmt.Sprintf("%s IN (SELECT TOP (%d) %s FROM %v%v)",
table.PrimaryKeys[0], st.LimitN, table.PrimaryKeys[0],
session.Engine.Quote(session.Statement.TableName()), condSQL), condArgs...)
condSQL, condArgs, _ = builder.ToSQL(cond)
if len(condSQL) > 0 {
condSQL = "WHERE " + condSQL
}
} else {
top = fmt.Sprintf("TOP (%d) ", st.LimitN)
}
} }
} }

View File

@ -356,7 +356,6 @@ func TestUpdate1(t *testing.T) {
And("departname = ?", ""). And("departname = ?", "").
And("detail_id = ?", 0). And("detail_id = ?", 0).
And("is_man = ?", 0). And("is_man = ?", 0).
And("created IS NOT NULL").
Get(&Userinfo{}) Get(&Userinfo{})
if err != nil { if err != nil {
t.Error(err) t.Error(err)

View File

@ -26,7 +26,7 @@ var colStrTests = []struct {
} }
func TestColumnsStringGeneration(t *testing.T) { func TestColumnsStringGeneration(t *testing.T) {
if dbType == "postgres" { if dbType == "postgres" || dbType == "mssql" {
return return
} }

View File

@ -10,6 +10,7 @@ import (
"testing" "testing"
"time" "time"
"github.com/go-xorm/core"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
@ -328,6 +329,11 @@ func TestExtends2(t *testing.T) {
Uid: sender.Id, Uid: sender.Id,
ToUid: receiver.Id, ToUid: receiver.Id,
} }
if testEngine.dialect.DBType() == core.MSSQL {
_, err = testEngine.Exec("SET IDENTITY_INSERT message ON")
assert.NoError(t, err)
}
_, err = testEngine.Insert(&msg) _, err = testEngine.Insert(&msg)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
@ -395,6 +401,10 @@ func TestExtends3(t *testing.T) {
Uid: sender.Id, Uid: sender.Id,
ToUid: receiver.Id, ToUid: receiver.Id,
} }
if testEngine.dialect.DBType() == core.MSSQL {
_, err = testEngine.Exec("SET IDENTITY_INSERT message ON")
assert.NoError(t, err)
}
_, err = testEngine.Insert(&msg) _, err = testEngine.Insert(&msg)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
@ -478,6 +488,10 @@ func TestExtends4(t *testing.T) {
Content: "test", Content: "test",
Uid: sender.Id, Uid: sender.Id,
} }
if testEngine.dialect.DBType() == core.MSSQL {
_, err = testEngine.Exec("SET IDENTITY_INSERT message ON")
assert.NoError(t, err)
}
_, err = testEngine.Insert(&msg) _, err = testEngine.Insert(&msg)
if err != nil { if err != nil {
t.Error(err) t.Error(err)

View File

@ -38,7 +38,7 @@ func TestGonicMapperID(t *testing.T) {
for _, tb := range tables { for _, tb := range tables {
if tb.Name == "id_gonic_mapper" { if tb.Name == "id_gonic_mapper" {
if len(tb.PKColumns()) != 1 && !tb.PKColumns()[0].IsPrimaryKey && !tb.PKColumns()[0].IsPrimaryKey { if len(tb.PKColumns()) != 1 || tb.PKColumns()[0].Name != "id" {
t.Fatal(tb) t.Fatal(tb)
} }
return return
@ -75,7 +75,7 @@ func TestSameMapperID(t *testing.T) {
for _, tb := range tables { for _, tb := range tables {
if tb.Name == "IDSameMapper" { if tb.Name == "IDSameMapper" {
if len(tb.PKColumns()) != 1 && !tb.PKColumns()[0].IsPrimaryKey && !tb.PKColumns()[0].IsPrimaryKey { if len(tb.PKColumns()) != 1 || tb.PKColumns()[0].Name != "id" {
t.Fatal(tb) t.Fatal(tb)
} }
return return

1
test_mssql.sh Executable file
View File

@ -0,0 +1 @@
go test -db=mssql -conn_str="server=192.168.1.58;user id=sa;password=123456;database=xorm_test"

View File

@ -7,6 +7,7 @@ import (
"strings" "strings"
"testing" "testing"
_ "github.com/denisenkom/go-mssqldb"
_ "github.com/go-sql-driver/mysql" _ "github.com/go-sql-driver/mysql"
"github.com/go-xorm/core" "github.com/go-xorm/core"
_ "github.com/lib/pq" _ "github.com/lib/pq"
@ -45,7 +46,10 @@ func createEngine(dbType, connStr string) error {
for _, table := range tables { for _, table := range tables {
tableNames = append(tableNames, table.Name) tableNames = append(tableNames, table.Name)
} }
return testEngine.DropTables(tableNames...) if err = testEngine.DropTables(tableNames...); err != nil {
return err
}
return nil
} }
func prepareEngine() error { func prepareEngine() error {
@ -70,8 +74,8 @@ func TestMain(m *testing.M) {
connString = *ptrConnStr connString = *ptrConnStr
} }
dbs := strings.Split(*db, ";") dbs := strings.Split(*db, "::")
conns := strings.Split(connString, ";") conns := strings.Split(connString, "::")
var res int var res int
for i := 0; i < len(dbs); i++ { for i := 0; i < len(dbs); i++ {