Skip to content

Commit

Permalink
Exec support conversion data (#1970)
Browse files Browse the repository at this point in the history
  • Loading branch information
lunny committed Aug 7, 2023
1 parent 94882e3 commit ac84217
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 2 deletions.
14 changes: 12 additions & 2 deletions convert/conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,21 @@ import (
"time"
)

// ConversionFrom is an inteface to allow retrieve data from database
type ConversionFrom interface {
FromDB([]byte) error
}

// ConversionTo is an interface to allow store data to database
type ConversionTo interface {
ToDB() ([]byte, error)
}

// Conversion is an interface. A type implements Conversion will according
// the custom method to fill into database and retrieve from database.
type Conversion interface {
FromDB([]byte) error
ToDB() ([]byte, error)
ConversionFrom
ConversionTo
}

// ErrNilPtr represents an error
Expand Down
17 changes: 17 additions & 0 deletions internal/statements/statement.go
Original file line number Diff line number Diff line change
Expand Up @@ -644,6 +644,23 @@ func (statement *Statement) convertSQLOrArgs(sqlOrArgs ...interface{}) (string,
newArgs = append(newArgs, v.In(statement.defaultTimeZone).Format("2006-01-02 15:04:05"))
} else if v, ok := arg.(*time.Time); ok && v != nil {
newArgs = append(newArgs, v.In(statement.defaultTimeZone).Format("2006-01-02 15:04:05"))
} else if v, ok := arg.(convert.ConversionTo); ok {
r, err := v.ToDB()
if err != nil {
return "", nil, err
}
if r != nil {
// for nvarchar column on mssql, bytes have to be converted as ucs-2 external of driver
// for binary column, a string will be converted as bytes directly. So we have to
// convert bytes as string
if statement.dialect.URI().DBType == schemas.MSSQL {
newArgs = append(newArgs, string(r))
} else {
newArgs = append(newArgs, r)
}
} else {
newArgs = append(newArgs, nil)
}
} else {
newArgs = append(newArgs, arg)
}
Expand Down
47 changes: 47 additions & 0 deletions tests/session_raw_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import (
"testing"
"time"

"xorm.io/xorm/convert"

"github.com/stretchr/testify/assert"
)

Expand Down Expand Up @@ -65,3 +67,48 @@ func TestExecTime(t *testing.T) {
assert.True(t, has)
assert.EqualValues(t, now.In(testEngine.GetTZLocation()).Format("2006-01-02 15:04:05"), uet.Created.Format("2006-01-02 15:04:05"))
}

type ConversionData struct {
MyData string
}

var _ convert.Conversion = new(ConversionData)

func (c ConversionData) ToDB() ([]byte, error) {
return []byte(c.MyData), nil
}

func (c *ConversionData) FromDB(bs []byte) error {
if bs != nil {
c.MyData = string(bs)
}
return nil
}

func TestExecCustomTypes(t *testing.T) {
assert.NoError(t, PrepareEngine())

type UserinfoExec struct {
Uid int
Name string
Data string
}

assert.NoError(t, testEngine.Sync2(new(UserinfoExec)))

res, err := testEngine.Exec("INSERT INTO "+testEngine.TableName("`userinfo_exec`", true)+" (uid, name,data) VALUES (?, ?, ?)",
1, "user", ConversionData{"data"})
assert.NoError(t, err)
cnt, err := res.RowsAffected()
assert.NoError(t, err)
assert.EqualValues(t, 1, cnt)

results, err := testEngine.QueryString("select * from " + testEngine.TableName("userinfo_exec", true))
assert.NoError(t, err)
assert.EqualValues(t, 1, len(results))
id, err := strconv.Atoi(results[0]["uid"])
assert.NoError(t, err)
assert.EqualValues(t, 1, id)
assert.Equal(t, "user", results[0]["name"])
assert.EqualValues(t, "data", results[0]["data"])
}

0 comments on commit ac84217

Please sign in to comment.