mirror of https://github.com/go-gorm/gorm.git
MSSQL Create() fix: Add LastInsertIDReturningSuffix to dialect (#2690)
* MSSQL Create() fix: Add LastInsertIDReturningSuffix to dialect Per https://github.com/denisenkom/go-mssqldb/issues/355 * MSSQL Create() fix: Added OUTPUT query to Create() builder
This commit is contained in:
parent
1bca5dbdd9
commit
820b5f244a
|
@ -101,10 +101,11 @@ func createCallback(scope *Scope) {
|
||||||
}
|
}
|
||||||
|
|
||||||
lastInsertIDReturningSuffix := scope.Dialect().LastInsertIDReturningSuffix(quotedTableName, returningColumn)
|
lastInsertIDReturningSuffix := scope.Dialect().LastInsertIDReturningSuffix(quotedTableName, returningColumn)
|
||||||
|
lastInsertIDOutputInterstitial := scope.Dialect().LastInsertIDOutputInterstitial(quotedTableName, returningColumn, columns)
|
||||||
|
|
||||||
if len(columns) == 0 {
|
if len(columns) == 0 {
|
||||||
scope.Raw(fmt.Sprintf(
|
scope.Raw(fmt.Sprintf(
|
||||||
"INSERT %v INTO %v %v%v%v",
|
"INSERT%v INTO %v %v%v%v",
|
||||||
addExtraSpaceIfExist(insertModifier),
|
addExtraSpaceIfExist(insertModifier),
|
||||||
quotedTableName,
|
quotedTableName,
|
||||||
scope.Dialect().DefaultValueStr(),
|
scope.Dialect().DefaultValueStr(),
|
||||||
|
@ -113,18 +114,19 @@ func createCallback(scope *Scope) {
|
||||||
))
|
))
|
||||||
} else {
|
} else {
|
||||||
scope.Raw(fmt.Sprintf(
|
scope.Raw(fmt.Sprintf(
|
||||||
"INSERT %v INTO %v (%v) VALUES (%v)%v%v",
|
"INSERT%v INTO %v (%v)%v VALUES (%v)%v%v",
|
||||||
addExtraSpaceIfExist(insertModifier),
|
addExtraSpaceIfExist(insertModifier),
|
||||||
scope.QuotedTableName(),
|
scope.QuotedTableName(),
|
||||||
strings.Join(columns, ","),
|
strings.Join(columns, ","),
|
||||||
|
addExtraSpaceIfExist(lastInsertIDOutputInterstitial),
|
||||||
strings.Join(placeholders, ","),
|
strings.Join(placeholders, ","),
|
||||||
addExtraSpaceIfExist(extraOption),
|
addExtraSpaceIfExist(extraOption),
|
||||||
addExtraSpaceIfExist(lastInsertIDReturningSuffix),
|
addExtraSpaceIfExist(lastInsertIDReturningSuffix),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
// execute create sql
|
// execute create sql: no primaryField
|
||||||
if lastInsertIDReturningSuffix == "" || primaryField == nil {
|
if primaryField == nil {
|
||||||
if result, err := scope.SQLDB().Exec(scope.SQL, scope.SQLVars...); scope.Err(err) == nil {
|
if result, err := scope.SQLDB().Exec(scope.SQL, scope.SQLVars...); scope.Err(err) == nil {
|
||||||
// set rows affected count
|
// set rows affected count
|
||||||
scope.db.RowsAffected, _ = result.RowsAffected()
|
scope.db.RowsAffected, _ = result.RowsAffected()
|
||||||
|
@ -136,16 +138,35 @@ func createCallback(scope *Scope) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
return
|
||||||
if primaryField.Field.CanAddr() {
|
|
||||||
if err := scope.SQLDB().QueryRow(scope.SQL, scope.SQLVars...).Scan(primaryField.Field.Addr().Interface()); scope.Err(err) == nil {
|
|
||||||
primaryField.IsBlank = false
|
|
||||||
scope.db.RowsAffected = 1
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
scope.Err(ErrUnaddressable)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// execute create sql: lastInsertID implemention for majority of dialects
|
||||||
|
if lastInsertIDReturningSuffix == "" && lastInsertIDOutputInterstitial == "" {
|
||||||
|
if result, err := scope.SQLDB().Exec(scope.SQL, scope.SQLVars...); scope.Err(err) == nil {
|
||||||
|
// set rows affected count
|
||||||
|
scope.db.RowsAffected, _ = result.RowsAffected()
|
||||||
|
|
||||||
|
// set primary value to primary field
|
||||||
|
if primaryField != nil && primaryField.IsBlank {
|
||||||
|
if primaryValue, err := result.LastInsertId(); scope.Err(err) == nil {
|
||||||
|
scope.Err(primaryField.Set(primaryValue))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// execute create sql: dialects with additional lastInsertID requirements (currently postgres & mssql)
|
||||||
|
if primaryField.Field.CanAddr() {
|
||||||
|
if err := scope.SQLDB().QueryRow(scope.SQL, scope.SQLVars...).Scan(primaryField.Field.Addr().Interface()); scope.Err(err) == nil {
|
||||||
|
primaryField.IsBlank = false
|
||||||
|
scope.db.RowsAffected = 1
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
scope.Err(ErrUnaddressable)
|
||||||
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,8 @@ type Dialect interface {
|
||||||
LimitAndOffsetSQL(limit, offset interface{}) string
|
LimitAndOffsetSQL(limit, offset interface{}) string
|
||||||
// SelectFromDummyTable return select values, for most dbs, `SELECT values` just works, mysql needs `SELECT value FROM DUAL`
|
// SelectFromDummyTable return select values, for most dbs, `SELECT values` just works, mysql needs `SELECT value FROM DUAL`
|
||||||
SelectFromDummyTable() string
|
SelectFromDummyTable() string
|
||||||
|
// LastInsertIDOutputInterstitial most dbs support LastInsertId, but mssql needs to use `OUTPUT`
|
||||||
|
LastInsertIDOutputInterstitial(tableName, columnName string, columns []string) string
|
||||||
// LastInsertIdReturningSuffix most dbs support LastInsertId, but postgres needs to use `RETURNING`
|
// LastInsertIdReturningSuffix most dbs support LastInsertId, but postgres needs to use `RETURNING`
|
||||||
LastInsertIDReturningSuffix(tableName, columnName string) string
|
LastInsertIDReturningSuffix(tableName, columnName string) string
|
||||||
// DefaultValueStr
|
// DefaultValueStr
|
||||||
|
|
|
@ -157,6 +157,10 @@ func (commonDialect) SelectFromDummyTable() string {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (commonDialect) LastInsertIDOutputInterstitial(tableName, columnName string, columns []string) string {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
func (commonDialect) LastInsertIDReturningSuffix(tableName, columnName string) string {
|
func (commonDialect) LastInsertIDReturningSuffix(tableName, columnName string) string {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
|
@ -120,6 +120,10 @@ func (s postgres) CurrentDatabase() (name string) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s postgres) LastInsertIDOutputInterstitial(tableName, key string, columns []string) string {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
func (s postgres) LastInsertIDReturningSuffix(tableName, key string) string {
|
func (s postgres) LastInsertIDReturningSuffix(tableName, key string) string {
|
||||||
return fmt.Sprintf("RETURNING %v.%v", tableName, key)
|
return fmt.Sprintf("RETURNING %v.%v", tableName, key)
|
||||||
}
|
}
|
||||||
|
|
|
@ -190,6 +190,14 @@ func (mssql) SelectFromDummyTable() string {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (mssql) LastInsertIDOutputInterstitial(tableName, columnName string, columns []string) string {
|
||||||
|
if len(columns) == 0 {
|
||||||
|
// No OUTPUT to query
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("OUTPUT Inserted.%v", columnName)
|
||||||
|
}
|
||||||
|
|
||||||
func (mssql) LastInsertIDReturningSuffix(tableName, columnName string) string {
|
func (mssql) LastInsertIDReturningSuffix(tableName, columnName string) string {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue