GORM support for MSSQL, passes all tests

This commit is contained in:
Joel Trost 2014-09-15 13:03:14 -07:00
parent facd84deec
commit f79e1a2ef6
9 changed files with 74 additions and 18 deletions

View File

@ -16,6 +16,10 @@ func (s *commonDialect) SupportLastInsertId() bool {
return true return true
} }
func (s *commonDialect) HasTop() bool {
return false
}
func (d *commonDialect) SqlTag(value reflect.Value, size int) string { func (d *commonDialect) SqlTag(value reflect.Value, size int) string {
switch value.Kind() { switch value.Kind() {
case reflect.Bool: case reflect.Bool:

View File

@ -11,6 +11,7 @@ var timeType = reflect.TypeOf(time.Time{})
type Dialect interface { type Dialect interface {
BinVar(i int) string BinVar(i int) string
SupportLastInsertId() bool SupportLastInsertId() bool
HasTop() bool
SqlTag(value reflect.Value, size int) string SqlTag(value reflect.Value, size int) string
PrimaryKeyTag(value reflect.Value, size int) string PrimaryKeyTag(value reflect.Value, size int) string
ReturningStr(key string) string ReturningStr(key string) string

View File

@ -51,7 +51,9 @@ func Open(dialect string, drivesources ...string) (DB, error) {
source = drivesources[1] source = drivesources[1]
} }
db = DB{dialect: NewDialect(dialect), tagIdentifier: "sql", logger: defaultLogger, callback: DefaultCallback, source: source, values: map[string]interface{}{}} db = DB{dialect: NewDialect(dialect), tagIdentifier: "sql",
logger: defaultLogger, callback: DefaultCallback, source: source,
values: map[string]interface{}{}}
db.db, err = sql.Open(driver, source) db.db, err = sql.Open(driver, source)
db.parent = &db db.parent = &db
} }

View File

@ -35,6 +35,9 @@ func init() {
case "postgres": case "postgres":
fmt.Println("testing postgres...") fmt.Println("testing postgres...")
DB, err = gorm.Open("postgres", "user=gorm DB.ame=gorm sslmode=disable") DB, err = gorm.Open("postgres", "user=gorm DB.ame=gorm sslmode=disable")
case "mssql":
fmt.Println("testing mssql...")
DB, err = gorm.Open("mssql", "server=SERVER_HERE;database=DB_HERE;user id=USER_HERE;password=PW_HERE;port=1433")
default: default:
fmt.Println("testing sqlite3...") fmt.Println("testing sqlite3...")
DB, err = gorm.Open("sqlite3", "/tmp/gorm.db") DB, err = gorm.Open("sqlite3", "/tmp/gorm.db")
@ -445,6 +448,11 @@ func TestTimeWithZone(t *testing.T) {
for index, vtime := range times { for index, vtime := range times {
name := "time_with_zone_" + strconv.Itoa(index) name := "time_with_zone_" + strconv.Itoa(index)
user := User{Name: name, Birthday: vtime} user := User{Name: name, Birthday: vtime}
//mssql does not support time zones
if dialect := os.Getenv("GORM_DIALECT"); dialect == "mssql" {
user.Birthday = vtime.UTC()
}
DB.Save(&user) DB.Save(&user)
if user.Birthday.UTC().Format(format) != "2013-02-18 17:51:49 +0000" { if user.Birthday.UTC().Format(format) != "2013-02-18 17:51:49 +0000" {
t.Errorf("User's birthday should not be changed after save") t.Errorf("User's birthday should not be changed after save")

View File

@ -17,6 +17,10 @@ func (s *mysql) SupportLastInsertId() bool {
return true return true
} }
func (s *mysql) HasTop() bool {
return false
}
func (d *mysql) SqlTag(value reflect.Value, size int) string { func (d *mysql) SqlTag(value reflect.Value, size int) string {
switch value.Kind() { switch value.Kind() {
case reflect.Bool: case reflect.Bool:

View File

@ -20,6 +20,10 @@ func (s *postgres) SupportLastInsertId() bool {
return false return false
} }
func (s *postgres) HasTop() bool {
return false
}
func (d *postgres) SqlTag(value reflect.Value, size int) string { func (d *postgres) SqlTag(value reflect.Value, size int) string {
switch value.Kind() { switch value.Kind() {
case reflect.Bool: case reflect.Bool:

View File

@ -244,10 +244,9 @@ func TestOrderAndPluck(t *testing.T) {
} }
var ages1, ages2 []int64 var ages1, ages2 []int64
scopedb.Order("age desc").Pluck("age", &ages1).Order("age").Pluck("age", &ages2) scopedb.Order("age desc").Pluck("age", &ages1).Pluck("age", &ages2)
if !reflect.DeepEqual(ages1, ages2) { if !reflect.DeepEqual(ages1, ages2) {
t.Errorf("The first order is the primary order") t.Errorf("The first order is the primary order") }
}
var ages3, ages4 []int64 var ages3, ages4 []int64
scopedb.Model(&User{}).Order("age desc").Pluck("age", &ages3).Order("age", true).Pluck("age", &ages4) scopedb.Model(&User{}).Order("age desc").Pluck("age", &ages3).Order("age", true).Pluck("age", &ages4)

View File

@ -196,20 +196,46 @@ func (s *Scope) orderSql() string {
} }
func (s *Scope) limitSql() string { func (s *Scope) limitSql() string {
if !s.Dialect().HasTop() {
if len(s.Search.Limit) == 0 { if len(s.Search.Limit) == 0 {
return "" return ""
} else { } else {
return " LIMIT " + s.Search.Limit return " LIMIT " + s.Search.Limit
} }
} else{
return ""
}
}
func (s *Scope) topSql() string{
if s.Dialect().HasTop() && len(s.Search.Offset) == 0 {
if len(s.Search.Limit) == 0 {
return ""
} else{
return " TOP(" + s.Search.Limit + ")"
}
} else{
return ""
} else {
return " LIMIT " + s.Search.Limit
}
} }
func (s *Scope) offsetSql() string { func (s *Scope) offsetSql() string {
if len(s.Search.Offset) == 0 { if len(s.Search.Offset) == 0 {
return "" return ""
} else {
if s.Dialect().HasTop(){
sql := " OFFSET " + s.Search.Offset + " ROW "
if len(s.Search.Limit) > 0{
sql += "FETCH NEXT " + s.Search.Limit + " ROWS ONLY"
}
return sql
}else{ }else{
return " OFFSET " + s.Search.Offset return " OFFSET " + s.Search.Offset
} }
} }
}
func (s *Scope) groupSql() string { func (s *Scope) groupSql() string {
if len(s.Search.Group) == 0 { if len(s.Search.Group) == 0 {
@ -235,7 +261,11 @@ func (scope *Scope) prepareQuerySql() {
if scope.Search.Raw { if scope.Search.Raw {
scope.Raw(strings.TrimLeft(scope.CombinedConditionSql(), "WHERE ")) scope.Raw(strings.TrimLeft(scope.CombinedConditionSql(), "WHERE "))
} else { } else {
<<<<<<< HEAD
scope.Raw(fmt.Sprintf("SELECT %v FROM %v %v", scope.selectSql(), scope.QuotedTableName(), scope.CombinedConditionSql())) scope.Raw(fmt.Sprintf("SELECT %v FROM %v %v", scope.selectSql(), scope.QuotedTableName(), scope.CombinedConditionSql()))
=======
scope.Raw(fmt.Sprintf("SELECT %v %v FROM %v %v", scope.topSql(), scope.selectSql(), scope.QuotedTableName(), scope.CombinedConditionSql()))
>>>>>>> 15a20a4... GORM support for MSSQL, passes all tests
} }
return return
} }

View File

@ -15,6 +15,10 @@ func (s *sqlite3) SupportLastInsertId() bool {
return true return true
} }
func (s *sqlite3) HasTop() bool {
return false
}
func (s *sqlite3) SqlTag(value reflect.Value, size int) string { func (s *sqlite3) SqlTag(value reflect.Value, size int) string {
switch value.Kind() { switch value.Kind() {
case reflect.Bool: case reflect.Bool: