support different text type with JSON type

This commit is contained in:
Lunny Xiao 2017-07-20 20:07:54 +08:00
parent 774f83c1bc
commit 18362d2340
No known key found for this signature in database
GPG Key ID: C3B7C91B632F738A
14 changed files with 88 additions and 16 deletions

View File

@ -243,7 +243,7 @@ func (db *mssql) SqlType(c *core.Column) string {
c.Length = 7 c.Length = 7
case core.MediumInt: case core.MediumInt:
res = core.Int res = core.Int
case core.Text, core.MediumText, core.TinyText, core.LongText, core.Json: case core.Text, core.MediumText, core.TinyText, core.LongText:
res = core.Varchar + "(MAX)" res = core.Varchar + "(MAX)"
case core.Double: case core.Double:
res = core.Real res = core.Real

View File

@ -222,8 +222,6 @@ func (db *mysql) 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.Json:
res = core.Text
default: default:
res = t res = t
} }

View File

@ -519,7 +519,7 @@ func (db *oracle) SqlType(c *core.Column) string {
res = "TIMESTAMP WITH TIME ZONE" res = "TIMESTAMP WITH TIME ZONE"
case core.Float, core.Double, core.Numeric, core.Decimal: case core.Float, core.Double, core.Numeric, core.Decimal:
res = "NUMBER" res = "NUMBER"
case core.Text, core.MediumText, core.LongText, core.Json: case core.Text, core.MediumText, core.LongText:
res = "CLOB" res = "CLOB"
case core.Char, core.Varchar, core.TinyText: case core.Char, core.Varchar, core.TinyText:
res = "VARCHAR2" res = "VARCHAR2"

View File

@ -165,7 +165,7 @@ func (db *sqlite3) SqlType(c *core.Column) string {
case core.TimeStampz: case core.TimeStampz:
return core.Text return core.Text
case core.Char, core.Varchar, core.NVarchar, core.TinyText, case core.Char, core.Varchar, core.NVarchar, core.TinyText,
core.Text, core.MediumText, core.LongText, core.Json: core.Text, core.MediumText, core.LongText:
return core.Text return core.Text
case core.Bit, core.TinyInt, core.SmallInt, core.MediumInt, core.Int, core.Integer, core.BigInt: case core.Bit, core.TinyInt, core.SmallInt, core.MediumInt, core.Int, core.Integer, core.BigInt:
return core.Integer return core.Integer

View File

@ -1023,7 +1023,6 @@ func (engine *Engine) mapType(v reflect.Value) (*core.Table, error) {
} }
table.AddColumn(col) table.AddColumn(col)
} // end for } // end for
if idFieldColName != "" && len(table.PrimaryKeys) == 0 { if idFieldColName != "" && len(table.PrimaryKeys) == 0 {

View File

@ -34,7 +34,7 @@ func (engine *Engine) buildConds(table *core.Table, bean interface{},
if engine.dialect.DBType() == core.MSSQL && (col.SQLType.Name == core.Text || col.SQLType.IsBlob() || col.SQLType.Name == core.TimeStampz) { if engine.dialect.DBType() == core.MSSQL && (col.SQLType.Name == core.Text || col.SQLType.IsBlob() || col.SQLType.Name == core.TimeStampz) {
continue continue
} }
if col.SQLType.IsJson() { if col.IsJSON || col.SQLType.IsJson() {
continue continue
} }
@ -142,7 +142,7 @@ func (engine *Engine) buildConds(table *core.Table, bean interface{},
continue continue
} }
} else { } else {
if col.SQLType.IsJson() { if col.IsJSON || col.SQLType.IsJson() {
if col.SQLType.IsText() { if col.SQLType.IsText() {
bytes, err := json.Marshal(fieldValue.Interface()) bytes, err := json.Marshal(fieldValue.Interface())
if err != nil { if err != nil {

View File

@ -408,7 +408,7 @@ func (session *Session) slice2Bean(scanResults []interface{}, fields []string, f
fieldType := fieldValue.Type() fieldType := fieldValue.Type()
hasAssigned := false hasAssigned := false
if col.SQLType.IsJson() { if col.IsJSON || col.SQLType.IsJson() {
var bs []byte var bs []byte
if rawValueType.Kind() == reflect.String { if rawValueType.Kind() == reflect.String {
bs = []byte(vv.String()) bs = []byte(vv.String())
@ -584,7 +584,7 @@ func (session *Session) slice2Bean(scanResults []interface{}, fields []string, f
session.Engine.logger.Error("sql.Sanner error:", err.Error()) session.Engine.logger.Error("sql.Sanner error:", err.Error())
hasAssigned = false hasAssigned = false
} }
} else if col.SQLType.IsJson() { } else if col.IsJSON || col.SQLType.IsJson() {
if rawValueType.Kind() == reflect.String { if rawValueType.Kind() == reflect.String {
hasAssigned = true hasAssigned = true
x := reflect.New(fieldType) x := reflect.New(fieldType)

View File

@ -591,7 +591,7 @@ func (session *Session) value2Interface(col *core.Column, fieldValue reflect.Val
return tf, nil return tf, nil
} }
if !col.SQLType.IsJson() { if !(col.IsJSON || col.SQLType.IsJson()) {
// !<winxxp>! 增加支持driver.Valuer接口的结构如sql.NullString // !<winxxp>! 增加支持driver.Valuer接口的结构如sql.NullString
if v, ok := fieldValue.Interface().(driver.Valuer); ok { if v, ok := fieldValue.Interface().(driver.Valuer); ok {
return v.Value() return v.Value()

View File

@ -8,6 +8,7 @@ import (
"testing" "testing"
"time" "time"
"github.com/go-xorm/core"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
@ -21,6 +22,12 @@ func TestDelete(t *testing.T) {
assert.NoError(t, testEngine.Sync2(new(UserinfoDelete))) assert.NoError(t, testEngine.Sync2(new(UserinfoDelete)))
var err error
if testEngine.dialect.DBType() == core.MSSQL {
_, err = testEngine.Exec("SET IDENTITY_INSERT " + testEngine.TableMapper.Obj2Table("UserinfoDelete") + " ON")
assert.NoError(t, err)
}
user := UserinfoDelete{Uid: 1} user := UserinfoDelete{Uid: 1}
cnt, err := testEngine.Insert(&user) cnt, err := testEngine.Insert(&user)
assert.NoError(t, err) assert.NoError(t, err)

View File

@ -37,10 +37,18 @@ func (session *Session) Exist(bean ...interface{}) (bool, error) {
return false, err return false, err
} }
sqlStr = fmt.Sprintf("SELECT * FROM %s WHERE %s LIMIT 1", tableName, condSQL) if session.Engine.dialect.DBType() == core.MSSQL {
sqlStr = fmt.Sprintf("SELECT TOP 1 * FROM %s WHERE %s", tableName, condSQL)
} else {
sqlStr = fmt.Sprintf("SELECT * FROM %s WHERE %s LIMIT 1", tableName, condSQL)
}
args = condArgs args = condArgs
} else { } else {
sqlStr = fmt.Sprintf("SELECT * FROM %s LIMIT 1", tableName) if session.Engine.dialect.DBType() == core.MSSQL {
sqlStr = fmt.Sprintf("SELECT TOP 1 * FROM %s", tableName)
} else {
sqlStr = fmt.Sprintf("SELECT * FROM %s LIMIT 1", tableName)
}
args = []interface{}{} args = []interface{}{}
} }
} else { } else {

View File

@ -380,7 +380,7 @@ func buildUpdates(engine *Engine, table *core.Table, bean interface{},
} else if nulType, ok := fieldValue.Interface().(driver.Valuer); ok { } else if nulType, ok := fieldValue.Interface().(driver.Valuer); ok {
val, _ = nulType.Value() val, _ = nulType.Value()
} else { } else {
if !col.SQLType.IsJson() { if !(col.IsJSON || col.SQLType.IsJson()) {
engine.autoMapType(fieldValue) engine.autoMapType(fieldValue)
if table, ok := engine.Tables[fieldValue.Type()]; ok { if table, ok := engine.Tables[fieldValue.Type()]; ok {
if len(table.PrimaryKeys) == 1 { if len(table.PrimaryKeys) == 1 {

17
tag.go
View File

@ -55,12 +55,16 @@ var (
"CACHE": CacheTagHandler, "CACHE": CacheTagHandler,
"NOCACHE": NoCacheTagHandler, "NOCACHE": NoCacheTagHandler,
"COMMENT": CommentTagHandler, "COMMENT": CommentTagHandler,
"JSON": JSONTagHandler,
} }
) )
func init() { func init() {
for k := range core.SqlTypes { for k := range core.SqlTypes {
defaultTagHandlers[k] = SQLTypeTagHandler // don't overwrite
if _, ok := defaultTagHandlers[k]; !ok {
defaultTagHandlers[k] = SQLTypeTagHandler
}
} }
} }
@ -241,8 +245,19 @@ func SQLTypeTagHandler(ctx *tagContext) error {
return nil return nil
} }
// JSONTagHandler handle json tag
func JSONTagHandler(ctx *tagContext) error {
fmt.Println("fdsfafadfs")
ctx.col.IsJSON = true
if len(ctx.params) == 0 {
ctx.col.SQLType = core.SQLType{Name: core.Text}
}
return nil
}
// ExtendsTagHandler describes extends tag handler // ExtendsTagHandler describes extends tag handler
func ExtendsTagHandler(ctx *tagContext) error { func ExtendsTagHandler(ctx *tagContext) error {
ctx.ignoreNext = true
var fieldValue = ctx.fieldValue var fieldValue = ctx.fieldValue
switch fieldValue.Kind() { switch fieldValue.Kind() {
case reflect.Ptr: case reflect.Ptr:

View File

@ -270,3 +270,48 @@ func TestTagComment(t *testing.T) {
assert.EqualValues(t, 1, len(tables[0].Columns())) assert.EqualValues(t, 1, len(tables[0].Columns()))
assert.EqualValues(t, "主键", tables[0].Columns()[0].Comment) assert.EqualValues(t, "主键", tables[0].Columns()[0].Comment)
} }
func TestTagJSON(t *testing.T) {
assert.NoError(t, prepareEngine())
type TestTagJSON1 struct {
Stings []string `xorm:"json"`
}
assert.NoError(t, testEngine.Sync2(new(TestTagJSON1)))
table := testEngine.TableInfo(new(TestTagJSON1))
assert.NotNil(t, table)
assert.EqualValues(t, 1, len(table.Columns()))
assert.True(t, table.Columns()[0].IsJSON)
assert.EqualValues(t, "TEXT", table.Columns()[0].SQLType.Name)
tables, err := testEngine.DBMetas()
assert.NoError(t, err)
assert.EqualValues(t, 1, len(tables))
assert.EqualValues(t, 1, len(tables[0].Columns()))
if testEngine.dialect.DBType() != core.MSSQL {
assert.EqualValues(t, "TEXT", tables[0].Columns()[0].SQLType.Name)
}
assert.NoError(t, testEngine.DropTables(new(TestTagJSON1)))
type TestTagJSON2 struct {
Stings []string `xorm:"json MediumText"`
}
assert.NoError(t, testEngine.Sync2(new(TestTagJSON2)))
table = testEngine.TableInfo(new(TestTagJSON2))
assert.NotNil(t, table)
assert.EqualValues(t, 1, len(table.Columns()))
assert.True(t, table.Columns()[0].IsJSON)
assert.EqualValues(t, "MEDIUMTEXT", table.Columns()[0].SQLType.Name)
tables, err = testEngine.DBMetas()
assert.NoError(t, err)
assert.EqualValues(t, 1, len(tables))
assert.EqualValues(t, 1, len(tables[0].Columns()))
if testEngine.dialect.DBType() == core.MYSQL {
assert.EqualValues(t, "MEDIUMTEXT", tables[0].Columns()[0].SQLType.Name)
}
}

View File

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