Merge branch 'master' into master
This commit is contained in:
commit
b61a1ee6f6
15
CHANGELOG.md
15
CHANGELOG.md
|
@ -3,6 +3,21 @@
|
||||||
This changelog goes through all the changes that have been made in each release
|
This changelog goes through all the changes that have been made in each release
|
||||||
without substantial changes to our git log.
|
without substantial changes to our git log.
|
||||||
|
|
||||||
|
## [1.1.0](https://gitea.com/xorm/xorm/releases/tag/1.1.0) - 2021-05-14
|
||||||
|
|
||||||
|
* FEATURES
|
||||||
|
* Unsigned Support for mysql (#1889)
|
||||||
|
* Support modernc.org/sqlite (#1850)
|
||||||
|
* TESTING
|
||||||
|
* More tests (#1890)
|
||||||
|
* MISC
|
||||||
|
* Byte strings in postgres aren't 0x... (#1906)
|
||||||
|
* Fix another bug with #1872 (#1905)
|
||||||
|
* Fix two issues with dumptables (#1903)
|
||||||
|
* Fix comments (#1896)
|
||||||
|
* Fix comments (#1893)
|
||||||
|
* MariaDB 10.5 adds a suffix on old datatypes (#1885)
|
||||||
|
|
||||||
## [1.0.7](https://gitea.com/xorm/xorm/pulls?q=&type=all&state=closed&milestone=1336) - 2021-01-21
|
## [1.0.7](https://gitea.com/xorm/xorm/pulls?q=&type=all&state=closed&milestone=1336) - 2021-01-21
|
||||||
|
|
||||||
* BUGFIXES
|
* BUGFIXES
|
||||||
|
|
2
Makefile
2
Makefile
|
@ -243,4 +243,4 @@ test-tidb\#%: go-check
|
||||||
|
|
||||||
.PHONY: vet
|
.PHONY: vet
|
||||||
vet:
|
vet:
|
||||||
$(GO) vet $(shell $(GO) list ./...)
|
$(GO) vet $(shell $(GO) list ./...)
|
||||||
|
|
15
core/db.go
15
core/db.go
|
@ -23,6 +23,7 @@ var (
|
||||||
DefaultCacheSize = 200
|
DefaultCacheSize = 200
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// MapToSlice map query and struct as sql and args
|
||||||
func MapToSlice(query string, mp interface{}) (string, []interface{}, error) {
|
func MapToSlice(query string, mp interface{}) (string, []interface{}, error) {
|
||||||
vv := reflect.ValueOf(mp)
|
vv := reflect.ValueOf(mp)
|
||||||
if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Map {
|
if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Map {
|
||||||
|
@ -44,6 +45,7 @@ func MapToSlice(query string, mp interface{}) (string, []interface{}, error) {
|
||||||
return query, args, err
|
return query, args, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// StructToSlice converts a query and struct as sql and args
|
||||||
func StructToSlice(query string, st interface{}) (string, []interface{}, error) {
|
func StructToSlice(query string, st interface{}) (string, []interface{}, error) {
|
||||||
vv := reflect.ValueOf(st)
|
vv := reflect.ValueOf(st)
|
||||||
if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Struct {
|
if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Struct {
|
||||||
|
@ -176,6 +178,7 @@ func (db *DB) QueryMap(query string, mp interface{}) (*Rows, error) {
|
||||||
return db.QueryMapContext(context.Background(), query, mp)
|
return db.QueryMapContext(context.Background(), query, mp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// QueryStructContext query rows with struct
|
||||||
func (db *DB) QueryStructContext(ctx context.Context, query string, st interface{}) (*Rows, error) {
|
func (db *DB) QueryStructContext(ctx context.Context, query string, st interface{}) (*Rows, error) {
|
||||||
query, args, err := StructToSlice(query, st)
|
query, args, err := StructToSlice(query, st)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -184,10 +187,12 @@ func (db *DB) QueryStructContext(ctx context.Context, query string, st interface
|
||||||
return db.QueryContext(ctx, query, args...)
|
return db.QueryContext(ctx, query, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// QueryStruct query rows with struct
|
||||||
func (db *DB) QueryStruct(query string, st interface{}) (*Rows, error) {
|
func (db *DB) QueryStruct(query string, st interface{}) (*Rows, error) {
|
||||||
return db.QueryStructContext(context.Background(), query, st)
|
return db.QueryStructContext(context.Background(), query, st)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// QueryRowContext query row with args
|
||||||
func (db *DB) QueryRowContext(ctx context.Context, query string, args ...interface{}) *Row {
|
func (db *DB) QueryRowContext(ctx context.Context, query string, args ...interface{}) *Row {
|
||||||
rows, err := db.QueryContext(ctx, query, args...)
|
rows, err := db.QueryContext(ctx, query, args...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -196,10 +201,12 @@ func (db *DB) QueryRowContext(ctx context.Context, query string, args ...interfa
|
||||||
return &Row{rows, nil}
|
return &Row{rows, nil}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// QueryRow query row with args
|
||||||
func (db *DB) QueryRow(query string, args ...interface{}) *Row {
|
func (db *DB) QueryRow(query string, args ...interface{}) *Row {
|
||||||
return db.QueryRowContext(context.Background(), query, args...)
|
return db.QueryRowContext(context.Background(), query, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// QueryRowMapContext query row with map
|
||||||
func (db *DB) QueryRowMapContext(ctx context.Context, query string, mp interface{}) *Row {
|
func (db *DB) QueryRowMapContext(ctx context.Context, query string, mp interface{}) *Row {
|
||||||
query, args, err := MapToSlice(query, mp)
|
query, args, err := MapToSlice(query, mp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -208,10 +215,12 @@ func (db *DB) QueryRowMapContext(ctx context.Context, query string, mp interface
|
||||||
return db.QueryRowContext(ctx, query, args...)
|
return db.QueryRowContext(ctx, query, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// QueryRowMap query row with map
|
||||||
func (db *DB) QueryRowMap(query string, mp interface{}) *Row {
|
func (db *DB) QueryRowMap(query string, mp interface{}) *Row {
|
||||||
return db.QueryRowMapContext(context.Background(), query, mp)
|
return db.QueryRowMapContext(context.Background(), query, mp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// QueryRowStructContext query row with struct
|
||||||
func (db *DB) QueryRowStructContext(ctx context.Context, query string, st interface{}) *Row {
|
func (db *DB) QueryRowStructContext(ctx context.Context, query string, st interface{}) *Row {
|
||||||
query, args, err := StructToSlice(query, st)
|
query, args, err := StructToSlice(query, st)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -220,6 +229,7 @@ func (db *DB) QueryRowStructContext(ctx context.Context, query string, st interf
|
||||||
return db.QueryRowContext(ctx, query, args...)
|
return db.QueryRowContext(ctx, query, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// QueryRowStruct query row with struct
|
||||||
func (db *DB) QueryRowStruct(query string, st interface{}) *Row {
|
func (db *DB) QueryRowStruct(query string, st interface{}) *Row {
|
||||||
return db.QueryRowStructContext(context.Background(), query, st)
|
return db.QueryRowStructContext(context.Background(), query, st)
|
||||||
}
|
}
|
||||||
|
@ -239,10 +249,12 @@ func (db *DB) ExecMapContext(ctx context.Context, query string, mp interface{})
|
||||||
return db.ExecContext(ctx, query, args...)
|
return db.ExecContext(ctx, query, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ExecMap exec query with map
|
||||||
func (db *DB) ExecMap(query string, mp interface{}) (sql.Result, error) {
|
func (db *DB) ExecMap(query string, mp interface{}) (sql.Result, error) {
|
||||||
return db.ExecMapContext(context.Background(), query, mp)
|
return db.ExecMapContext(context.Background(), query, mp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ExecStructContext exec query with map
|
||||||
func (db *DB) ExecStructContext(ctx context.Context, query string, st interface{}) (sql.Result, error) {
|
func (db *DB) ExecStructContext(ctx context.Context, query string, st interface{}) (sql.Result, error) {
|
||||||
query, args, err := StructToSlice(query, st)
|
query, args, err := StructToSlice(query, st)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -251,6 +263,7 @@ func (db *DB) ExecStructContext(ctx context.Context, query string, st interface{
|
||||||
return db.ExecContext(ctx, query, args...)
|
return db.ExecContext(ctx, query, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ExecContext exec query with args
|
||||||
func (db *DB) ExecContext(ctx context.Context, query string, args ...interface{}) (sql.Result, error) {
|
func (db *DB) ExecContext(ctx context.Context, query string, args ...interface{}) (sql.Result, error) {
|
||||||
hookCtx := contexts.NewContextHook(ctx, query, args)
|
hookCtx := contexts.NewContextHook(ctx, query, args)
|
||||||
ctx, err := db.beforeProcess(hookCtx)
|
ctx, err := db.beforeProcess(hookCtx)
|
||||||
|
@ -265,6 +278,7 @@ func (db *DB) ExecContext(ctx context.Context, query string, args ...interface{}
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ExecStruct exec query with struct
|
||||||
func (db *DB) ExecStruct(query string, st interface{}) (sql.Result, error) {
|
func (db *DB) ExecStruct(query string, st interface{}) (sql.Result, error) {
|
||||||
return db.ExecStructContext(context.Background(), query, st)
|
return db.ExecStructContext(context.Background(), query, st)
|
||||||
}
|
}
|
||||||
|
@ -288,6 +302,7 @@ func (db *DB) afterProcess(c *contexts.ContextHook) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddHook adds hook
|
||||||
func (db *DB) AddHook(h ...contexts.Hook) {
|
func (db *DB) AddHook(h ...contexts.Hook) {
|
||||||
db.hooks.AddHook(h...)
|
db.hooks.AddHook(h...)
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ import (
|
||||||
var (
|
var (
|
||||||
dbtype = flag.String("dbtype", "sqlite3", "database type")
|
dbtype = flag.String("dbtype", "sqlite3", "database type")
|
||||||
dbConn = flag.String("dbConn", "./db_test.db", "database connect string")
|
dbConn = flag.String("dbConn", "./db_test.db", "database connect string")
|
||||||
createTableSql string
|
createTableSQL string
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMain(m *testing.M) {
|
func TestMain(m *testing.M) {
|
||||||
|
@ -29,12 +29,12 @@ func TestMain(m *testing.M) {
|
||||||
|
|
||||||
switch *dbtype {
|
switch *dbtype {
|
||||||
case "sqlite3", "sqlite":
|
case "sqlite3", "sqlite":
|
||||||
createTableSql = "CREATE TABLE IF NOT EXISTS `user` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NULL, " +
|
createTableSQL = "CREATE TABLE IF NOT EXISTS `user` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NULL, " +
|
||||||
"`title` TEXT NULL, `age` FLOAT NULL, `alias` TEXT NULL, `nick_name` TEXT NULL, `created` datetime);"
|
"`title` TEXT NULL, `age` FLOAT NULL, `alias` TEXT NULL, `nick_name` TEXT NULL, `created` datetime);"
|
||||||
case "mysql":
|
case "mysql":
|
||||||
fallthrough
|
fallthrough
|
||||||
default:
|
default:
|
||||||
createTableSql = "CREATE TABLE IF NOT EXISTS `user` (`id` INTEGER PRIMARY KEY AUTO_INCREMENT NOT NULL, `name` TEXT NULL, " +
|
createTableSQL = "CREATE TABLE IF NOT EXISTS `user` (`id` INTEGER PRIMARY KEY AUTO_INCREMENT NOT NULL, `name` TEXT NULL, " +
|
||||||
"`title` TEXT NULL, `age` FLOAT NULL, `alias` TEXT NULL, `nick_name` TEXT NULL, `created` datetime);"
|
"`title` TEXT NULL, `age` FLOAT NULL, `alias` TEXT NULL, `nick_name` TEXT NULL, `created` datetime);"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ func BenchmarkOriQuery(b *testing.B) {
|
||||||
}
|
}
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
_, err = db.Exec(createTableSql)
|
_, err = db.Exec(createTableSQL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Error(err)
|
b.Error(err)
|
||||||
}
|
}
|
||||||
|
@ -121,7 +121,7 @@ func BenchmarkStructQuery(b *testing.B) {
|
||||||
}
|
}
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
_, err = db.Exec(createTableSql)
|
_, err = db.Exec(createTableSQL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Error(err)
|
b.Error(err)
|
||||||
}
|
}
|
||||||
|
@ -166,7 +166,7 @@ func BenchmarkStruct2Query(b *testing.B) {
|
||||||
}
|
}
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
_, err = db.Exec(createTableSql)
|
_, err = db.Exec(createTableSQL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Error(err)
|
b.Error(err)
|
||||||
}
|
}
|
||||||
|
@ -212,7 +212,7 @@ func BenchmarkSliceInterfaceQuery(b *testing.B) {
|
||||||
}
|
}
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
_, err = db.Exec(createTableSql)
|
_, err = db.Exec(createTableSQL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Error(err)
|
b.Error(err)
|
||||||
}
|
}
|
||||||
|
@ -270,7 +270,7 @@ func BenchmarkSliceInterfaceQuery(b *testing.B) {
|
||||||
}
|
}
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
_, err = db.Exec(createTableSql)
|
_, err = db.Exec(createTableSQL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Error(err)
|
b.Error(err)
|
||||||
}
|
}
|
||||||
|
@ -321,7 +321,7 @@ func BenchmarkSliceStringQuery(b *testing.B) {
|
||||||
}
|
}
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
_, err = db.Exec(createTableSql)
|
_, err = db.Exec(createTableSQL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Error(err)
|
b.Error(err)
|
||||||
}
|
}
|
||||||
|
@ -372,7 +372,7 @@ func BenchmarkMapInterfaceQuery(b *testing.B) {
|
||||||
}
|
}
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
_, err = db.Exec(createTableSql)
|
_, err = db.Exec(createTableSQL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Error(err)
|
b.Error(err)
|
||||||
}
|
}
|
||||||
|
@ -426,7 +426,7 @@ func BenchmarkMapInterfaceQuery(b *testing.B) {
|
||||||
}
|
}
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
_, err = db.Exec(createTableSql)
|
_, err = db.Exec(createTableSQL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Error(err)
|
b.Error(err)
|
||||||
}
|
}
|
||||||
|
@ -473,7 +473,7 @@ func BenchmarkMapStringQuery(b *testing.B) {
|
||||||
}
|
}
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
_, err = db.Exec(createTableSql)
|
_, err = db.Exec(createTableSQL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Error(err)
|
b.Error(err)
|
||||||
}
|
}
|
||||||
|
@ -519,7 +519,7 @@ func BenchmarkExec(b *testing.B) {
|
||||||
}
|
}
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
_, err = db.Exec(createTableSql)
|
_, err = db.Exec(createTableSQL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Error(err)
|
b.Error(err)
|
||||||
}
|
}
|
||||||
|
@ -544,7 +544,7 @@ func BenchmarkExecMap(b *testing.B) {
|
||||||
}
|
}
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
_, err = db.Exec(createTableSql)
|
_, err = db.Exec(createTableSQL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Error(err)
|
b.Error(err)
|
||||||
}
|
}
|
||||||
|
@ -577,7 +577,7 @@ func TestExecMap(t *testing.T) {
|
||||||
}
|
}
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
_, err = db.Exec(createTableSql)
|
_, err = db.Exec(createTableSQL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
|
@ -620,7 +620,7 @@ func TestExecStruct(t *testing.T) {
|
||||||
}
|
}
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
_, err = db.Exec(createTableSql)
|
_, err = db.Exec(createTableSQL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
|
@ -663,7 +663,7 @@ func BenchmarkExecStruct(b *testing.B) {
|
||||||
}
|
}
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
_, err = db.Exec(createTableSql)
|
_, err = db.Exec(createTableSQL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Error(err)
|
b.Error(err)
|
||||||
}
|
}
|
||||||
|
|
20
core/rows.go
20
core/rows.go
|
@ -11,11 +11,13 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Rows represents rows of table
|
||||||
type Rows struct {
|
type Rows struct {
|
||||||
*sql.Rows
|
*sql.Rows
|
||||||
db *DB
|
db *DB
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ToMapString returns all records
|
||||||
func (rs *Rows) ToMapString() ([]map[string]string, error) {
|
func (rs *Rows) ToMapString() ([]map[string]string, error) {
|
||||||
cols, err := rs.Columns()
|
cols, err := rs.Columns()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -34,7 +36,7 @@ func (rs *Rows) ToMapString() ([]map[string]string, error) {
|
||||||
return results, nil
|
return results, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// scan data to a struct's pointer according field index
|
// ScanStructByIndex scan data to a struct's pointer according field index
|
||||||
func (rs *Rows) ScanStructByIndex(dest ...interface{}) error {
|
func (rs *Rows) ScanStructByIndex(dest ...interface{}) error {
|
||||||
if len(dest) == 0 {
|
if len(dest) == 0 {
|
||||||
return errors.New("at least one struct")
|
return errors.New("at least one struct")
|
||||||
|
@ -94,7 +96,7 @@ func fieldByName(v reflect.Value, name string) reflect.Value {
|
||||||
return reflect.Zero(t)
|
return reflect.Zero(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
// scan data to a struct's pointer according field name
|
// ScanStructByName scan data to a struct's pointer according field name
|
||||||
func (rs *Rows) ScanStructByName(dest interface{}) error {
|
func (rs *Rows) ScanStructByName(dest interface{}) error {
|
||||||
vv := reflect.ValueOf(dest)
|
vv := reflect.ValueOf(dest)
|
||||||
if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Struct {
|
if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Struct {
|
||||||
|
@ -120,7 +122,7 @@ func (rs *Rows) ScanStructByName(dest interface{}) error {
|
||||||
return rs.Rows.Scan(newDest...)
|
return rs.Rows.Scan(newDest...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// scan data to a slice's pointer, slice's length should equal to columns' number
|
// ScanSlice scan data to a slice's pointer, slice's length should equal to columns' number
|
||||||
func (rs *Rows) ScanSlice(dest interface{}) error {
|
func (rs *Rows) ScanSlice(dest interface{}) error {
|
||||||
vv := reflect.ValueOf(dest)
|
vv := reflect.ValueOf(dest)
|
||||||
if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Slice {
|
if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Slice {
|
||||||
|
@ -155,7 +157,7 @@ func (rs *Rows) ScanSlice(dest interface{}) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// scan data to a map's pointer
|
// ScanMap scan data to a map's pointer
|
||||||
func (rs *Rows) ScanMap(dest interface{}) error {
|
func (rs *Rows) ScanMap(dest interface{}) error {
|
||||||
vv := reflect.ValueOf(dest)
|
vv := reflect.ValueOf(dest)
|
||||||
if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Map {
|
if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Map {
|
||||||
|
@ -187,6 +189,7 @@ func (rs *Rows) ScanMap(dest interface{}) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Row reprents a row of a tab
|
||||||
type Row struct {
|
type Row struct {
|
||||||
rows *Rows
|
rows *Rows
|
||||||
// One of these two will be non-nil:
|
// One of these two will be non-nil:
|
||||||
|
@ -205,6 +208,7 @@ func NewRow(rows *Rows, err error) *Row {
|
||||||
return &Row{rows, err}
|
return &Row{rows, err}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Columns returns all columns of the row
|
||||||
func (row *Row) Columns() ([]string, error) {
|
func (row *Row) Columns() ([]string, error) {
|
||||||
if row.err != nil {
|
if row.err != nil {
|
||||||
return nil, row.err
|
return nil, row.err
|
||||||
|
@ -212,6 +216,7 @@ func (row *Row) Columns() ([]string, error) {
|
||||||
return row.rows.Columns()
|
return row.rows.Columns()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Scan retrieves all row column values
|
||||||
func (row *Row) Scan(dest ...interface{}) error {
|
func (row *Row) Scan(dest ...interface{}) error {
|
||||||
if row.err != nil {
|
if row.err != nil {
|
||||||
return row.err
|
return row.err
|
||||||
|
@ -238,6 +243,7 @@ func (row *Row) Scan(dest ...interface{}) error {
|
||||||
return row.rows.Close()
|
return row.rows.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ScanStructByName retrieves all row column values into a struct
|
||||||
func (row *Row) ScanStructByName(dest interface{}) error {
|
func (row *Row) ScanStructByName(dest interface{}) error {
|
||||||
if row.err != nil {
|
if row.err != nil {
|
||||||
return row.err
|
return row.err
|
||||||
|
@ -258,6 +264,7 @@ func (row *Row) ScanStructByName(dest interface{}) error {
|
||||||
return row.rows.Close()
|
return row.rows.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ScanStructByIndex retrieves all row column values into a struct
|
||||||
func (row *Row) ScanStructByIndex(dest interface{}) error {
|
func (row *Row) ScanStructByIndex(dest interface{}) error {
|
||||||
if row.err != nil {
|
if row.err != nil {
|
||||||
return row.err
|
return row.err
|
||||||
|
@ -278,7 +285,7 @@ func (row *Row) ScanStructByIndex(dest interface{}) error {
|
||||||
return row.rows.Close()
|
return row.rows.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
// scan data to a slice's pointer, slice's length should equal to columns' number
|
// ScanSlice scan data to a slice's pointer, slice's length should equal to columns' number
|
||||||
func (row *Row) ScanSlice(dest interface{}) error {
|
func (row *Row) ScanSlice(dest interface{}) error {
|
||||||
if row.err != nil {
|
if row.err != nil {
|
||||||
return row.err
|
return row.err
|
||||||
|
@ -300,7 +307,7 @@ func (row *Row) ScanSlice(dest interface{}) error {
|
||||||
return row.rows.Close()
|
return row.rows.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
// scan data to a map's pointer
|
// ScanMap scan data to a map's pointer
|
||||||
func (row *Row) ScanMap(dest interface{}) error {
|
func (row *Row) ScanMap(dest interface{}) error {
|
||||||
if row.err != nil {
|
if row.err != nil {
|
||||||
return row.err
|
return row.err
|
||||||
|
@ -322,6 +329,7 @@ func (row *Row) ScanMap(dest interface{}) error {
|
||||||
return row.rows.Close()
|
return row.rows.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ToMapString returns all clumns of this record
|
||||||
func (row *Row) ToMapString() (map[string]string, error) {
|
func (row *Row) ToMapString() (map[string]string, error) {
|
||||||
cols, err := row.Columns()
|
cols, err := row.Columns()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -10,12 +10,14 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// NullTime defines a customize type NullTime
|
||||||
type NullTime time.Time
|
type NullTime time.Time
|
||||||
|
|
||||||
var (
|
var (
|
||||||
_ driver.Valuer = NullTime{}
|
_ driver.Valuer = NullTime{}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Scan implements driver.Valuer
|
||||||
func (ns *NullTime) Scan(value interface{}) error {
|
func (ns *NullTime) Scan(value interface{}) error {
|
||||||
if value == nil {
|
if value == nil {
|
||||||
return nil
|
return nil
|
||||||
|
@ -58,9 +60,11 @@ func convertTime(dest *NullTime, src interface{}) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EmptyScanner represents an empty scanner
|
||||||
type EmptyScanner struct {
|
type EmptyScanner struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Scan implements
|
||||||
func (EmptyScanner) Scan(src interface{}) error {
|
func (EmptyScanner) Scan(src interface{}) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
19
core/stmt.go
19
core/stmt.go
|
@ -21,6 +21,7 @@ type Stmt struct {
|
||||||
query string
|
query string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PrepareContext creates a prepare statement
|
||||||
func (db *DB) PrepareContext(ctx context.Context, query string) (*Stmt, error) {
|
func (db *DB) PrepareContext(ctx context.Context, query string) (*Stmt, error) {
|
||||||
names := make(map[string]int)
|
names := make(map[string]int)
|
||||||
var i int
|
var i int
|
||||||
|
@ -42,10 +43,12 @@ func (db *DB) PrepareContext(ctx context.Context, query string) (*Stmt, error) {
|
||||||
return &Stmt{stmt, db, names, query}, nil
|
return &Stmt{stmt, db, names, query}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Prepare creates a prepare statement
|
||||||
func (db *DB) Prepare(query string) (*Stmt, error) {
|
func (db *DB) Prepare(query string) (*Stmt, error) {
|
||||||
return db.PrepareContext(context.Background(), query)
|
return db.PrepareContext(context.Background(), query)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ExecMapContext execute with map
|
||||||
func (s *Stmt) ExecMapContext(ctx context.Context, mp interface{}) (sql.Result, error) {
|
func (s *Stmt) ExecMapContext(ctx context.Context, mp interface{}) (sql.Result, error) {
|
||||||
vv := reflect.ValueOf(mp)
|
vv := reflect.ValueOf(mp)
|
||||||
if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Map {
|
if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Map {
|
||||||
|
@ -59,10 +62,12 @@ func (s *Stmt) ExecMapContext(ctx context.Context, mp interface{}) (sql.Result,
|
||||||
return s.ExecContext(ctx, args...)
|
return s.ExecContext(ctx, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ExecMap executes with map
|
||||||
func (s *Stmt) ExecMap(mp interface{}) (sql.Result, error) {
|
func (s *Stmt) ExecMap(mp interface{}) (sql.Result, error) {
|
||||||
return s.ExecMapContext(context.Background(), mp)
|
return s.ExecMapContext(context.Background(), mp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ExecStructContext executes with struct
|
||||||
func (s *Stmt) ExecStructContext(ctx context.Context, st interface{}) (sql.Result, error) {
|
func (s *Stmt) ExecStructContext(ctx context.Context, st interface{}) (sql.Result, error) {
|
||||||
vv := reflect.ValueOf(st)
|
vv := reflect.ValueOf(st)
|
||||||
if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Struct {
|
if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Struct {
|
||||||
|
@ -76,10 +81,12 @@ func (s *Stmt) ExecStructContext(ctx context.Context, st interface{}) (sql.Resul
|
||||||
return s.ExecContext(ctx, args...)
|
return s.ExecContext(ctx, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ExecStruct executes with struct
|
||||||
func (s *Stmt) ExecStruct(st interface{}) (sql.Result, error) {
|
func (s *Stmt) ExecStruct(st interface{}) (sql.Result, error) {
|
||||||
return s.ExecStructContext(context.Background(), st)
|
return s.ExecStructContext(context.Background(), st)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ExecContext with args
|
||||||
func (s *Stmt) ExecContext(ctx context.Context, args ...interface{}) (sql.Result, error) {
|
func (s *Stmt) ExecContext(ctx context.Context, args ...interface{}) (sql.Result, error) {
|
||||||
hookCtx := contexts.NewContextHook(ctx, s.query, args)
|
hookCtx := contexts.NewContextHook(ctx, s.query, args)
|
||||||
ctx, err := s.db.beforeProcess(hookCtx)
|
ctx, err := s.db.beforeProcess(hookCtx)
|
||||||
|
@ -94,6 +101,7 @@ func (s *Stmt) ExecContext(ctx context.Context, args ...interface{}) (sql.Result
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// QueryContext query with args
|
||||||
func (s *Stmt) QueryContext(ctx context.Context, args ...interface{}) (*Rows, error) {
|
func (s *Stmt) QueryContext(ctx context.Context, args ...interface{}) (*Rows, error) {
|
||||||
hookCtx := contexts.NewContextHook(ctx, s.query, args)
|
hookCtx := contexts.NewContextHook(ctx, s.query, args)
|
||||||
ctx, err := s.db.beforeProcess(hookCtx)
|
ctx, err := s.db.beforeProcess(hookCtx)
|
||||||
|
@ -108,10 +116,12 @@ func (s *Stmt) QueryContext(ctx context.Context, args ...interface{}) (*Rows, er
|
||||||
return &Rows{rows, s.db}, nil
|
return &Rows{rows, s.db}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Query query with args
|
||||||
func (s *Stmt) Query(args ...interface{}) (*Rows, error) {
|
func (s *Stmt) Query(args ...interface{}) (*Rows, error) {
|
||||||
return s.QueryContext(context.Background(), args...)
|
return s.QueryContext(context.Background(), args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// QueryMapContext query with map
|
||||||
func (s *Stmt) QueryMapContext(ctx context.Context, mp interface{}) (*Rows, error) {
|
func (s *Stmt) QueryMapContext(ctx context.Context, mp interface{}) (*Rows, error) {
|
||||||
vv := reflect.ValueOf(mp)
|
vv := reflect.ValueOf(mp)
|
||||||
if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Map {
|
if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Map {
|
||||||
|
@ -126,10 +136,12 @@ func (s *Stmt) QueryMapContext(ctx context.Context, mp interface{}) (*Rows, erro
|
||||||
return s.QueryContext(ctx, args...)
|
return s.QueryContext(ctx, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// QueryMap query with map
|
||||||
func (s *Stmt) QueryMap(mp interface{}) (*Rows, error) {
|
func (s *Stmt) QueryMap(mp interface{}) (*Rows, error) {
|
||||||
return s.QueryMapContext(context.Background(), mp)
|
return s.QueryMapContext(context.Background(), mp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// QueryStructContext query with struct
|
||||||
func (s *Stmt) QueryStructContext(ctx context.Context, st interface{}) (*Rows, error) {
|
func (s *Stmt) QueryStructContext(ctx context.Context, st interface{}) (*Rows, error) {
|
||||||
vv := reflect.ValueOf(st)
|
vv := reflect.ValueOf(st)
|
||||||
if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Struct {
|
if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Struct {
|
||||||
|
@ -144,19 +156,23 @@ func (s *Stmt) QueryStructContext(ctx context.Context, st interface{}) (*Rows, e
|
||||||
return s.QueryContext(ctx, args...)
|
return s.QueryContext(ctx, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// QueryStruct query with struct
|
||||||
func (s *Stmt) QueryStruct(st interface{}) (*Rows, error) {
|
func (s *Stmt) QueryStruct(st interface{}) (*Rows, error) {
|
||||||
return s.QueryStructContext(context.Background(), st)
|
return s.QueryStructContext(context.Background(), st)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// QueryRowContext query row with args
|
||||||
func (s *Stmt) QueryRowContext(ctx context.Context, args ...interface{}) *Row {
|
func (s *Stmt) QueryRowContext(ctx context.Context, args ...interface{}) *Row {
|
||||||
rows, err := s.QueryContext(ctx, args...)
|
rows, err := s.QueryContext(ctx, args...)
|
||||||
return &Row{rows, err}
|
return &Row{rows, err}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// QueryRow query row with args
|
||||||
func (s *Stmt) QueryRow(args ...interface{}) *Row {
|
func (s *Stmt) QueryRow(args ...interface{}) *Row {
|
||||||
return s.QueryRowContext(context.Background(), args...)
|
return s.QueryRowContext(context.Background(), args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// QueryRowMapContext query row with map
|
||||||
func (s *Stmt) QueryRowMapContext(ctx context.Context, mp interface{}) *Row {
|
func (s *Stmt) QueryRowMapContext(ctx context.Context, mp interface{}) *Row {
|
||||||
vv := reflect.ValueOf(mp)
|
vv := reflect.ValueOf(mp)
|
||||||
if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Map {
|
if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Map {
|
||||||
|
@ -171,10 +187,12 @@ func (s *Stmt) QueryRowMapContext(ctx context.Context, mp interface{}) *Row {
|
||||||
return s.QueryRowContext(ctx, args...)
|
return s.QueryRowContext(ctx, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// QueryRowMap query row with map
|
||||||
func (s *Stmt) QueryRowMap(mp interface{}) *Row {
|
func (s *Stmt) QueryRowMap(mp interface{}) *Row {
|
||||||
return s.QueryRowMapContext(context.Background(), mp)
|
return s.QueryRowMapContext(context.Background(), mp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// QueryRowStructContext query row with struct
|
||||||
func (s *Stmt) QueryRowStructContext(ctx context.Context, st interface{}) *Row {
|
func (s *Stmt) QueryRowStructContext(ctx context.Context, st interface{}) *Row {
|
||||||
vv := reflect.ValueOf(st)
|
vv := reflect.ValueOf(st)
|
||||||
if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Struct {
|
if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Struct {
|
||||||
|
@ -189,6 +207,7 @@ func (s *Stmt) QueryRowStructContext(ctx context.Context, st interface{}) *Row {
|
||||||
return s.QueryRowContext(ctx, args...)
|
return s.QueryRowContext(ctx, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// QueryRowStruct query row with struct
|
||||||
func (s *Stmt) QueryRowStruct(st interface{}) *Row {
|
func (s *Stmt) QueryRowStruct(st interface{}) *Row {
|
||||||
return s.QueryRowStructContext(context.Background(), st)
|
return s.QueryRowStructContext(context.Background(), st)
|
||||||
}
|
}
|
||||||
|
|
10
core/tx.go
10
core/tx.go
|
@ -51,10 +51,7 @@ func (tx *Tx) Commit() error {
|
||||||
}
|
}
|
||||||
err = tx.Tx.Commit()
|
err = tx.Tx.Commit()
|
||||||
hookCtx.End(ctx, nil, err)
|
hookCtx.End(ctx, nil, err)
|
||||||
if err := tx.db.afterProcess(hookCtx); err != nil {
|
return tx.db.afterProcess(hookCtx)
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rollback rollback the transaction
|
// Rollback rollback the transaction
|
||||||
|
@ -66,10 +63,7 @@ func (tx *Tx) Rollback() error {
|
||||||
}
|
}
|
||||||
err = tx.Tx.Rollback()
|
err = tx.Tx.Rollback()
|
||||||
hookCtx.End(ctx, nil, err)
|
hookCtx.End(ctx, nil, err)
|
||||||
if err := tx.db.afterProcess(hookCtx); err != nil {
|
return tx.db.afterProcess(hookCtx)
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// PrepareContext prepare the query
|
// PrepareContext prepare the query
|
||||||
|
|
|
@ -824,6 +824,11 @@ func (db *postgres) SetQuotePolicy(quotePolicy QuotePolicy) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FormatBytes formats bytes
|
||||||
|
func (db *postgres) FormatBytes(bs []byte) string {
|
||||||
|
return fmt.Sprintf("E'\\x%x'", bs)
|
||||||
|
}
|
||||||
|
|
||||||
func (db *postgres) SQLType(c *schemas.Column) string {
|
func (db *postgres) SQLType(c *schemas.Column) string {
|
||||||
var res string
|
var res string
|
||||||
switch t := c.SQLType.Name; t {
|
switch t := c.SQLType.Name; t {
|
||||||
|
|
146
engine.go
146
engine.go
|
@ -21,6 +21,7 @@ import (
|
||||||
"xorm.io/xorm/contexts"
|
"xorm.io/xorm/contexts"
|
||||||
"xorm.io/xorm/core"
|
"xorm.io/xorm/core"
|
||||||
"xorm.io/xorm/dialects"
|
"xorm.io/xorm/dialects"
|
||||||
|
"xorm.io/xorm/internal/json"
|
||||||
"xorm.io/xorm/internal/utils"
|
"xorm.io/xorm/internal/utils"
|
||||||
"xorm.io/xorm/log"
|
"xorm.io/xorm/log"
|
||||||
"xorm.io/xorm/names"
|
"xorm.io/xorm/names"
|
||||||
|
@ -457,9 +458,26 @@ func formatColumnValue(dstDialect dialects.Dialect, d interface{}, col *schemas.
|
||||||
}
|
}
|
||||||
|
|
||||||
if col.SQLType.IsText() {
|
if col.SQLType.IsText() {
|
||||||
var v = fmt.Sprintf("%s", d)
|
var v string
|
||||||
|
switch reflect.TypeOf(d).Kind() {
|
||||||
|
case reflect.Struct, reflect.Array, reflect.Slice, reflect.Map:
|
||||||
|
bytes, err := json.DefaultJSONHandler.Marshal(d)
|
||||||
|
if err != nil {
|
||||||
|
v = fmt.Sprintf("%s", d)
|
||||||
|
} else {
|
||||||
|
v = string(bytes)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
v = fmt.Sprintf("%s", d)
|
||||||
|
}
|
||||||
|
|
||||||
return "'" + strings.Replace(v, "'", "''", -1) + "'"
|
return "'" + strings.Replace(v, "'", "''", -1) + "'"
|
||||||
} else if col.SQLType.IsTime() {
|
} else if col.SQLType.IsTime() {
|
||||||
|
if dstDialect.URI().DBType == schemas.MSSQL && col.SQLType.Name == schemas.DateTime {
|
||||||
|
if t, ok := d.(time.Time); ok {
|
||||||
|
return "'" + t.UTC().Format("2006-01-02 15:04:05") + "'"
|
||||||
|
}
|
||||||
|
}
|
||||||
var v = fmt.Sprintf("%s", d)
|
var v = fmt.Sprintf("%s", d)
|
||||||
if strings.HasSuffix(v, " +0000 UTC") {
|
if strings.HasSuffix(v, " +0000 UTC") {
|
||||||
return fmt.Sprintf("'%s'", v[0:len(v)-len(" +0000 UTC")])
|
return fmt.Sprintf("'%s'", v[0:len(v)-len(" +0000 UTC")])
|
||||||
|
@ -491,7 +509,7 @@ func formatColumnValue(dstDialect dialects.Dialect, d interface{}, col *schemas.
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("%v", strconv.FormatBool(v))
|
return fmt.Sprintf("%v", strconv.FormatBool(v))
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("%v", d)
|
return fmt.Sprintf("%d", d)
|
||||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||||
if col.SQLType.Name == schemas.Bool {
|
if col.SQLType.Name == schemas.Bool {
|
||||||
v := reflect.ValueOf(d).Uint() > 0
|
v := reflect.ValueOf(d).Uint() > 0
|
||||||
|
@ -503,7 +521,7 @@ func formatColumnValue(dstDialect dialects.Dialect, d interface{}, col *schemas.
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("%v", strconv.FormatBool(v))
|
return fmt.Sprintf("%v", strconv.FormatBool(v))
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("%v", d)
|
return fmt.Sprintf("%d", d)
|
||||||
default:
|
default:
|
||||||
return fmt.Sprintf("%v", d)
|
return fmt.Sprintf("%v", d)
|
||||||
}
|
}
|
||||||
|
@ -537,6 +555,8 @@ func (engine *Engine) dumpTables(tables []*schemas.Table, w io.Writer, tp ...sch
|
||||||
}
|
}
|
||||||
dstDialect.Init(&destURI)
|
dstDialect.Init(&destURI)
|
||||||
}
|
}
|
||||||
|
cacherMgr := caches.NewManager()
|
||||||
|
dstTableCache := tags.NewParser("xorm", dstDialect, engine.GetTableMapper(), engine.GetColumnMapper(), cacherMgr)
|
||||||
|
|
||||||
_, err := io.WriteString(w, fmt.Sprintf("/*Generated by xorm %s, from %s to %s*/\n\n",
|
_, err := io.WriteString(w, fmt.Sprintf("/*Generated by xorm %s, from %s to %s*/\n\n",
|
||||||
time.Now().In(engine.TZLocation).Format("2006-01-02 15:04:05"), engine.dialect.URI().DBType, dstDialect.URI().DBType))
|
time.Now().In(engine.TZLocation).Format("2006-01-02 15:04:05"), engine.dialect.URI().DBType, dstDialect.URI().DBType))
|
||||||
|
@ -545,9 +565,18 @@ func (engine *Engine) dumpTables(tables []*schemas.Table, w io.Writer, tp ...sch
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, table := range tables {
|
for i, table := range tables {
|
||||||
tableName := table.Name
|
dstTable := table
|
||||||
|
if table.Type != nil {
|
||||||
|
dstTable, err = dstTableCache.Parse(reflect.New(table.Type).Elem())
|
||||||
|
if err != nil {
|
||||||
|
engine.logger.Errorf("Unable to infer table for %s in new dialect. Error: %v", table.Name)
|
||||||
|
dstTable = table
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dstTableName := dstTable.Name
|
||||||
if dstDialect.URI().Schema != "" {
|
if dstDialect.URI().Schema != "" {
|
||||||
tableName = fmt.Sprintf("%s.%s", dstDialect.URI().Schema, table.Name)
|
dstTableName = fmt.Sprintf("%s.%s", dstDialect.URI().Schema, dstTable.Name)
|
||||||
}
|
}
|
||||||
originalTableName := table.Name
|
originalTableName := table.Name
|
||||||
if engine.dialect.URI().Schema != "" {
|
if engine.dialect.URI().Schema != "" {
|
||||||
|
@ -559,27 +588,30 @@ func (engine *Engine) dumpTables(tables []*schemas.Table, w io.Writer, tp ...sch
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sqls, _ := dstDialect.CreateTableSQL(table, tableName)
|
|
||||||
|
sqls, _ := dstDialect.CreateTableSQL(dstTable, dstTableName)
|
||||||
for _, s := range sqls {
|
for _, s := range sqls {
|
||||||
_, err = io.WriteString(w, s+";\n")
|
_, err = io.WriteString(w, s+";\n")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(table.PKColumns()) > 0 && dstDialect.URI().DBType == schemas.MSSQL {
|
if len(dstTable.PKColumns()) > 0 && dstDialect.URI().DBType == schemas.MSSQL {
|
||||||
fmt.Fprintf(w, "SET IDENTITY_INSERT [%s] ON;\n", table.Name)
|
fmt.Fprintf(w, "SET IDENTITY_INSERT [%s] ON;\n", dstTable.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, index := range table.Indexes {
|
for _, index := range dstTable.Indexes {
|
||||||
_, err = io.WriteString(w, dstDialect.CreateIndexSQL(table.Name, index)+";\n")
|
_, err = io.WriteString(w, dstDialect.CreateIndexSQL(dstTable.Name, index)+";\n")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cols := table.ColumnsSeq()
|
cols := table.ColumnsSeq()
|
||||||
|
dstCols := dstTable.ColumnsSeq()
|
||||||
|
|
||||||
colNames := engine.dialect.Quoter().Join(cols, ", ")
|
colNames := engine.dialect.Quoter().Join(cols, ", ")
|
||||||
destColNames := dstDialect.Quoter().Join(cols, ", ")
|
destColNames := dstDialect.Quoter().Join(dstCols, ", ")
|
||||||
|
|
||||||
rows, err := engine.DB().QueryContext(engine.defaultContext, "SELECT "+colNames+" FROM "+engine.Quote(originalTableName))
|
rows, err := engine.DB().QueryContext(engine.defaultContext, "SELECT "+colNames+" FROM "+engine.Quote(originalTableName))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -587,35 +619,83 @@ func (engine *Engine) dumpTables(tables []*schemas.Table, w io.Writer, tp ...sch
|
||||||
}
|
}
|
||||||
defer rows.Close()
|
defer rows.Close()
|
||||||
|
|
||||||
for rows.Next() {
|
if table.Type != nil {
|
||||||
dest := make([]interface{}, len(cols))
|
sess := engine.NewSession()
|
||||||
err = rows.ScanSlice(&dest)
|
defer sess.Close()
|
||||||
if err != nil {
|
for rows.Next() {
|
||||||
return err
|
beanValue := reflect.New(table.Type)
|
||||||
}
|
bean := beanValue.Interface()
|
||||||
|
fields, err := rows.Columns()
|
||||||
_, err = io.WriteString(w, "INSERT INTO "+dstDialect.Quoter().Quote(tableName)+" ("+destColNames+") VALUES (")
|
if err != nil {
|
||||||
if err != nil {
|
return err
|
||||||
return err
|
}
|
||||||
}
|
scanResults, err := sess.row2Slice(rows, fields, bean)
|
||||||
|
if err != nil {
|
||||||
var temp string
|
return err
|
||||||
for i, d := range dest {
|
}
|
||||||
col := table.GetColumn(cols[i])
|
|
||||||
if col == nil {
|
dataStruct := utils.ReflectValue(bean)
|
||||||
return errors.New("unknow column error")
|
_, err = sess.slice2Bean(scanResults, fields, bean, &dataStruct, table)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = io.WriteString(w, "INSERT INTO "+dstDialect.Quoter().Quote(dstTableName)+" ("+destColNames+") VALUES (")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var temp string
|
||||||
|
for _, d := range dstCols {
|
||||||
|
col := table.GetColumn(d)
|
||||||
|
if col == nil {
|
||||||
|
return errors.New("unknown column error")
|
||||||
|
}
|
||||||
|
|
||||||
|
fields := strings.Split(col.FieldName, ".")
|
||||||
|
field := dataStruct
|
||||||
|
for _, fieldName := range fields {
|
||||||
|
field = field.FieldByName(fieldName)
|
||||||
|
}
|
||||||
|
temp += "," + formatColumnValue(dstDialect, field.Interface(), col)
|
||||||
|
}
|
||||||
|
_, err = io.WriteString(w, temp[1:]+");\n")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
temp += "," + formatColumnValue(dstDialect, d, col)
|
|
||||||
}
|
}
|
||||||
_, err = io.WriteString(w, temp[1:]+");\n")
|
} else {
|
||||||
if err != nil {
|
for rows.Next() {
|
||||||
return err
|
dest := make([]interface{}, len(cols))
|
||||||
|
err = rows.ScanSlice(&dest)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = io.WriteString(w, "INSERT INTO "+dstDialect.Quoter().Quote(dstTableName)+" ("+destColNames+") VALUES (")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var temp string
|
||||||
|
for i, d := range dest {
|
||||||
|
col := table.GetColumn(cols[i])
|
||||||
|
if col == nil {
|
||||||
|
return errors.New("unknow column error")
|
||||||
|
}
|
||||||
|
|
||||||
|
temp += "," + formatColumnValue(dstDialect, d, col)
|
||||||
|
}
|
||||||
|
_, err = io.WriteString(w, temp[1:]+");\n")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: Hack for postgres
|
// FIXME: Hack for postgres
|
||||||
if dstDialect.URI().DBType == schemas.POSTGRES && table.AutoIncrColumn() != nil {
|
if dstDialect.URI().DBType == schemas.POSTGRES && table.AutoIncrColumn() != nil {
|
||||||
_, err = io.WriteString(w, "SELECT setval('"+tableName+"_id_seq', COALESCE((SELECT MAX("+table.AutoIncrColumn().Name+") + 1 FROM "+dstDialect.Quoter().Quote(tableName)+"), 1), false);\n")
|
_, err = io.WriteString(w, "SELECT setval('"+dstTableName+"_id_seq', COALESCE((SELECT MAX("+table.AutoIncrColumn().Name+") + 1 FROM "+dstDialect.Quoter().Quote(dstTableName)+"), 1), false);\n")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
1
go.mod
1
go.mod
|
@ -5,6 +5,7 @@ go 1.13
|
||||||
require (
|
require (
|
||||||
github.com/denisenkom/go-mssqldb v0.9.0
|
github.com/denisenkom/go-mssqldb v0.9.0
|
||||||
github.com/go-sql-driver/mysql v1.5.0
|
github.com/go-sql-driver/mysql v1.5.0
|
||||||
|
github.com/json-iterator/go v1.1.11
|
||||||
github.com/lib/pq v1.7.0
|
github.com/lib/pq v1.7.0
|
||||||
github.com/mattn/go-sqlite3 v1.14.6
|
github.com/mattn/go-sqlite3 v1.14.6
|
||||||
github.com/stretchr/testify v1.4.0
|
github.com/stretchr/testify v1.4.0
|
||||||
|
|
10
go.sum
10
go.sum
|
@ -1,7 +1,8 @@
|
||||||
gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a h1:lSA0F4e9A2NcQSqGqTOXqu2aRi/XEQxDCBwM8yJtE6s=
|
gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a h1:lSA0F4e9A2NcQSqGqTOXqu2aRi/XEQxDCBwM8yJtE6s=
|
||||||
gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a/go.mod h1:EXuID2Zs0pAQhH8yz+DNjUbjppKQzKFAn28TMYPB6IU=
|
gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a/go.mod h1:EXuID2Zs0pAQhH8yz+DNjUbjppKQzKFAn28TMYPB6IU=
|
||||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/denisenkom/go-mssqldb v0.9.0 h1:RSohk2RsiZqLZ0zCjtfn3S4Gp4exhpBWHyQ7D0yGjAk=
|
github.com/denisenkom/go-mssqldb v0.9.0 h1:RSohk2RsiZqLZ0zCjtfn3S4Gp4exhpBWHyQ7D0yGjAk=
|
||||||
github.com/denisenkom/go-mssqldb v0.9.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
|
github.com/denisenkom/go-mssqldb v0.9.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
|
||||||
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
|
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
|
||||||
|
@ -18,8 +19,11 @@ github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db h1:woRePGFeVFfLKN/pO
|
||||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||||
github.com/google/go-cmp v0.5.3 h1:x95R7cp+rSeeqAMI2knLtQ0DKlaBhv2NrtrOvafPHRo=
|
github.com/google/go-cmp v0.5.3 h1:x95R7cp+rSeeqAMI2knLtQ0DKlaBhv2NrtrOvafPHRo=
|
||||||
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
|
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
|
||||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||||
|
github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ=
|
||||||
|
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
|
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
|
||||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
|
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
|
||||||
github.com/lib/pq v1.7.0 h1:h93mCPfUSkaul3Ka/VG8uZdmW1uMHDGxzu0NWHuJmHY=
|
github.com/lib/pq v1.7.0 h1:h93mCPfUSkaul3Ka/VG8uZdmW1uMHDGxzu0NWHuJmHY=
|
||||||
|
@ -28,6 +32,10 @@ github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHX
|
||||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||||
github.com/mattn/go-sqlite3 v1.14.6 h1:dNPt6NO46WmLVt2DLNpwczCmdV5boIZ6g/tlDrlRUbg=
|
github.com/mattn/go-sqlite3 v1.14.6 h1:dNPt6NO46WmLVt2DLNpwczCmdV5boIZ6g/tlDrlRUbg=
|
||||||
github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
|
github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
|
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg=
|
||||||
|
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs=
|
github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs=
|
||||||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
|
|
|
@ -97,6 +97,7 @@ func TestDeleted(t *testing.T) {
|
||||||
// Test normal Find()
|
// Test normal Find()
|
||||||
var records1 []Deleted
|
var records1 []Deleted
|
||||||
err = testEngine.Where("`"+testEngine.GetColumnMapper().Obj2Table("Id")+"` > 0").Find(&records1, &Deleted{})
|
err = testEngine.Where("`"+testEngine.GetColumnMapper().Obj2Table("Id")+"` > 0").Find(&records1, &Deleted{})
|
||||||
|
assert.NoError(t, err)
|
||||||
assert.EqualValues(t, 3, len(records1))
|
assert.EqualValues(t, 3, len(records1))
|
||||||
|
|
||||||
// Test normal Get()
|
// Test normal Get()
|
||||||
|
@ -132,6 +133,7 @@ func TestDeleted(t *testing.T) {
|
||||||
record2 := &Deleted{}
|
record2 := &Deleted{}
|
||||||
has, err = testEngine.ID(2).Get(record2)
|
has, err = testEngine.ID(2).Get(record2)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
assert.True(t, has)
|
||||||
assert.True(t, record2.DeletedAt.IsZero())
|
assert.True(t, record2.DeletedAt.IsZero())
|
||||||
|
|
||||||
// Test find all records whatever `deleted`.
|
// Test find all records whatever `deleted`.
|
||||||
|
|
|
@ -653,6 +653,31 @@ func TestFindAndCount2(t *testing.T) {
|
||||||
assert.EqualValues(t, 0, cnt)
|
assert.EqualValues(t, 0, cnt)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type FindAndCountWithTableName struct {
|
||||||
|
Id int64
|
||||||
|
Name string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (FindAndCountWithTableName) TableName() string {
|
||||||
|
return "find_and_count_with_table_name1"
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFindAndCountWithTableName(t *testing.T) {
|
||||||
|
assert.NoError(t, PrepareEngine())
|
||||||
|
assertSync(t, new(FindAndCountWithTableName))
|
||||||
|
|
||||||
|
cnt, err := testEngine.Insert(&FindAndCountWithTableName{
|
||||||
|
Name: "1",
|
||||||
|
})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.EqualValues(t, 1, cnt)
|
||||||
|
|
||||||
|
var res []FindAndCountWithTableName
|
||||||
|
cnt, err = testEngine.FindAndCount(&res)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.EqualValues(t, 1, cnt)
|
||||||
|
}
|
||||||
|
|
||||||
type FindMapDevice struct {
|
type FindMapDevice struct {
|
||||||
Deviceid string `xorm:"pk"`
|
Deviceid string `xorm:"pk"`
|
||||||
Status int
|
Status int
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
// Copyright 2021 The Xorm Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build jsoniter
|
||||||
|
|
||||||
|
package json
|
||||||
|
|
||||||
|
import (
|
||||||
|
jsoniter "github.com/json-iterator/go"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
DefaultJSONHandler = JSONiter{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// JSONiter implements JSONInterface via jsoniter
|
||||||
|
type JSONiter struct{}
|
||||||
|
|
||||||
|
// Marshal implements JSONInterface
|
||||||
|
func (JSONiter) Marshal(v interface{}) ([]byte, error) {
|
||||||
|
return jsoniter.Marshal(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unmarshal implements JSONInterface
|
||||||
|
func (JSONiter) Unmarshal(data []byte, v interface{}) error {
|
||||||
|
return jsoniter.Unmarshal(data, v)
|
||||||
|
}
|
|
@ -12,6 +12,7 @@ import (
|
||||||
"xorm.io/xorm/schemas"
|
"xorm.io/xorm/schemas"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ConvertIDSQL converts SQL with id
|
||||||
func (statement *Statement) ConvertIDSQL(sqlStr string) string {
|
func (statement *Statement) ConvertIDSQL(sqlStr string) string {
|
||||||
if statement.RefTable != nil {
|
if statement.RefTable != nil {
|
||||||
cols := statement.RefTable.PKColumns()
|
cols := statement.RefTable.PKColumns()
|
||||||
|
@ -37,6 +38,7 @@ func (statement *Statement) ConvertIDSQL(sqlStr string) string {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ConvertUpdateSQL converts update SQL
|
||||||
func (statement *Statement) ConvertUpdateSQL(sqlStr string) (string, string) {
|
func (statement *Statement) ConvertUpdateSQL(sqlStr string) (string, string) {
|
||||||
if statement.RefTable == nil || len(statement.RefTable.PrimaryKeys) != 1 {
|
if statement.RefTable == nil || len(statement.RefTable.PrimaryKeys) != 1 {
|
||||||
return "", ""
|
return "", ""
|
||||||
|
|
|
@ -14,6 +14,7 @@ import (
|
||||||
"xorm.io/xorm/schemas"
|
"xorm.io/xorm/schemas"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// GenQuerySQL generate query SQL
|
||||||
func (statement *Statement) GenQuerySQL(sqlOrArgs ...interface{}) (string, []interface{}, error) {
|
func (statement *Statement) GenQuerySQL(sqlOrArgs ...interface{}) (string, []interface{}, error) {
|
||||||
if len(sqlOrArgs) > 0 {
|
if len(sqlOrArgs) > 0 {
|
||||||
return statement.ConvertSQLOrArgs(sqlOrArgs...)
|
return statement.ConvertSQLOrArgs(sqlOrArgs...)
|
||||||
|
@ -72,6 +73,7 @@ func (statement *Statement) GenQuerySQL(sqlOrArgs ...interface{}) (string, []int
|
||||||
return sqlStr, args, nil
|
return sqlStr, args, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GenSumSQL generates sum SQL
|
||||||
func (statement *Statement) GenSumSQL(bean interface{}, columns ...string) (string, []interface{}, error) {
|
func (statement *Statement) GenSumSQL(bean interface{}, columns ...string) (string, []interface{}, error) {
|
||||||
if statement.RawSQL != "" {
|
if statement.RawSQL != "" {
|
||||||
return statement.GenRawSQL(), statement.RawParams, nil
|
return statement.GenRawSQL(), statement.RawParams, nil
|
||||||
|
@ -102,6 +104,7 @@ func (statement *Statement) GenSumSQL(bean interface{}, columns ...string) (stri
|
||||||
return sqlStr, append(statement.joinArgs, condArgs...), nil
|
return sqlStr, append(statement.joinArgs, condArgs...), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GenGetSQL generates Get SQL
|
||||||
func (statement *Statement) GenGetSQL(bean interface{}) (string, []interface{}, error) {
|
func (statement *Statement) GenGetSQL(bean interface{}) (string, []interface{}, error) {
|
||||||
v := rValue(bean)
|
v := rValue(bean)
|
||||||
isStruct := v.Kind() == reflect.Struct
|
isStruct := v.Kind() == reflect.Struct
|
||||||
|
@ -316,6 +319,7 @@ func (statement *Statement) genSelectSQL(columnStr string, needLimit, needOrderB
|
||||||
return buf.String(), condArgs, nil
|
return buf.String(), condArgs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GenExistSQL generates Exist SQL
|
||||||
func (statement *Statement) GenExistSQL(bean ...interface{}) (string, []interface{}, error) {
|
func (statement *Statement) GenExistSQL(bean ...interface{}) (string, []interface{}, error) {
|
||||||
if statement.RawSQL != "" {
|
if statement.RawSQL != "" {
|
||||||
return statement.GenRawSQL(), statement.RawParams, nil
|
return statement.GenRawSQL(), statement.RawParams, nil
|
||||||
|
@ -385,6 +389,7 @@ func (statement *Statement) GenExistSQL(bean ...interface{}) (string, []interfac
|
||||||
return sqlStr, args, nil
|
return sqlStr, args, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GenFindSQL generates Find SQL
|
||||||
func (statement *Statement) GenFindSQL(autoCond builder.Cond) (string, []interface{}, error) {
|
func (statement *Statement) GenFindSQL(autoCond builder.Cond) (string, []interface{}, error) {
|
||||||
if statement.RawSQL != "" {
|
if statement.RawSQL != "" {
|
||||||
return statement.GenRawSQL(), statement.RawParams, nil
|
return statement.GenRawSQL(), statement.RawParams, nil
|
||||||
|
|
|
@ -90,14 +90,11 @@ func NewStatement(dialect dialects.Dialect, tagParser *tags.Parser, defaultTimeZ
|
||||||
return statement
|
return statement
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetTableName set table name
|
||||||
func (statement *Statement) SetTableName(tableName string) {
|
func (statement *Statement) SetTableName(tableName string) {
|
||||||
statement.tableName = tableName
|
statement.tableName = tableName
|
||||||
}
|
}
|
||||||
|
|
||||||
func (statement *Statement) omitStr() string {
|
|
||||||
return statement.dialect.Quoter().Join(statement.OmitColumnMap, " ,")
|
|
||||||
}
|
|
||||||
|
|
||||||
// GenRawSQL generates correct raw sql
|
// GenRawSQL generates correct raw sql
|
||||||
func (statement *Statement) GenRawSQL() string {
|
func (statement *Statement) GenRawSQL() string {
|
||||||
return statement.ReplaceQuote(statement.RawSQL)
|
return statement.ReplaceQuote(statement.RawSQL)
|
||||||
|
@ -112,6 +109,7 @@ func (statement *Statement) GenCondSQL(condOrBuilder interface{}) (string, []int
|
||||||
return statement.ReplaceQuote(condSQL), condArgs, nil
|
return statement.ReplaceQuote(condSQL), condArgs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReplaceQuote replace sql key words with quote
|
||||||
func (statement *Statement) ReplaceQuote(sql string) string {
|
func (statement *Statement) ReplaceQuote(sql string) string {
|
||||||
if sql == "" || statement.dialect.URI().DBType == schemas.MYSQL ||
|
if sql == "" || statement.dialect.URI().DBType == schemas.MYSQL ||
|
||||||
statement.dialect.URI().DBType == schemas.SQLITE {
|
statement.dialect.URI().DBType == schemas.SQLITE {
|
||||||
|
@ -591,7 +589,7 @@ func (statement *Statement) Having(conditions string) *Statement {
|
||||||
return statement
|
return statement
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unscoped always disable struct tag "deleted"
|
// SetUnscoped always disable struct tag "deleted"
|
||||||
func (statement *Statement) SetUnscoped() *Statement {
|
func (statement *Statement) SetUnscoped() *Statement {
|
||||||
statement.unscoped = true
|
statement.unscoped = true
|
||||||
return statement
|
return statement
|
||||||
|
@ -923,10 +921,7 @@ func (statement *Statement) mergeConds(bean interface{}) error {
|
||||||
statement.cond = statement.cond.And(autoCond)
|
statement.cond = statement.cond.And(autoCond)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := statement.ProcessIDParam(); err != nil {
|
return statement.ProcessIDParam()
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GenConds generates conditions
|
// GenConds generates conditions
|
||||||
|
|
|
@ -77,6 +77,7 @@ func convertArg(arg interface{}, convertFunc func(string) string) string {
|
||||||
|
|
||||||
const insertSelectPlaceHolder = true
|
const insertSelectPlaceHolder = true
|
||||||
|
|
||||||
|
// WriteArg writes an arg
|
||||||
func (statement *Statement) WriteArg(w *builder.BytesWriter, arg interface{}) error {
|
func (statement *Statement) WriteArg(w *builder.BytesWriter, arg interface{}) error {
|
||||||
switch argv := arg.(type) {
|
switch argv := arg.(type) {
|
||||||
case *builder.Builder:
|
case *builder.Builder:
|
||||||
|
@ -116,6 +117,7 @@ func (statement *Statement) WriteArg(w *builder.BytesWriter, arg interface{}) er
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WriteArgs writes args
|
||||||
func (statement *Statement) WriteArgs(w *builder.BytesWriter, args []interface{}) error {
|
func (statement *Statement) WriteArgs(w *builder.BytesWriter, args []interface{}) error {
|
||||||
for i, arg := range args {
|
for i, arg := range args {
|
||||||
if err := statement.WriteArg(w, arg); err != nil {
|
if err := statement.WriteArg(w, arg); err != nil {
|
||||||
|
|
|
@ -16,6 +16,7 @@ type Mapper interface {
|
||||||
Table2Obj(string) string
|
Table2Obj(string) string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CacheMapper represents a cache mapper
|
||||||
type CacheMapper struct {
|
type CacheMapper struct {
|
||||||
oriMapper Mapper
|
oriMapper Mapper
|
||||||
obj2tableCache map[string]string
|
obj2tableCache map[string]string
|
||||||
|
@ -24,12 +25,14 @@ type CacheMapper struct {
|
||||||
table2objMutex sync.RWMutex
|
table2objMutex sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewCacheMapper creates a cache mapper
|
||||||
func NewCacheMapper(mapper Mapper) *CacheMapper {
|
func NewCacheMapper(mapper Mapper) *CacheMapper {
|
||||||
return &CacheMapper{oriMapper: mapper, obj2tableCache: make(map[string]string),
|
return &CacheMapper{oriMapper: mapper, obj2tableCache: make(map[string]string),
|
||||||
table2objCache: make(map[string]string),
|
table2objCache: make(map[string]string),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Obj2Table implements Mapper
|
||||||
func (m *CacheMapper) Obj2Table(o string) string {
|
func (m *CacheMapper) Obj2Table(o string) string {
|
||||||
m.obj2tableMutex.RLock()
|
m.obj2tableMutex.RLock()
|
||||||
t, ok := m.obj2tableCache[o]
|
t, ok := m.obj2tableCache[o]
|
||||||
|
@ -45,6 +48,7 @@ func (m *CacheMapper) Obj2Table(o string) string {
|
||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Table2Obj implements Mapper
|
||||||
func (m *CacheMapper) Table2Obj(t string) string {
|
func (m *CacheMapper) Table2Obj(t string) string {
|
||||||
m.table2objMutex.RLock()
|
m.table2objMutex.RLock()
|
||||||
o, ok := m.table2objCache[t]
|
o, ok := m.table2objCache[t]
|
||||||
|
@ -60,15 +64,17 @@ func (m *CacheMapper) Table2Obj(t string) string {
|
||||||
return o
|
return o
|
||||||
}
|
}
|
||||||
|
|
||||||
// SameMapper implements IMapper and provides same name between struct and
|
// SameMapper implements Mapper and provides same name between struct and
|
||||||
// database table
|
// database table
|
||||||
type SameMapper struct {
|
type SameMapper struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Obj2Table implements Mapper
|
||||||
func (m SameMapper) Obj2Table(o string) string {
|
func (m SameMapper) Obj2Table(o string) string {
|
||||||
return o
|
return o
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Table2Obj implements Mapper
|
||||||
func (m SameMapper) Table2Obj(t string) string {
|
func (m SameMapper) Table2Obj(t string) string {
|
||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
@ -98,6 +104,7 @@ func snakeCasedName(name string) string {
|
||||||
return b2s(newstr)
|
return b2s(newstr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Obj2Table implements Mapper
|
||||||
func (mapper SnakeMapper) Obj2Table(name string) string {
|
func (mapper SnakeMapper) Obj2Table(name string) string {
|
||||||
return snakeCasedName(name)
|
return snakeCasedName(name)
|
||||||
}
|
}
|
||||||
|
@ -127,6 +134,7 @@ func titleCasedName(name string) string {
|
||||||
return b2s(newstr)
|
return b2s(newstr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Table2Obj implements Mapper
|
||||||
func (mapper SnakeMapper) Table2Obj(name string) string {
|
func (mapper SnakeMapper) Table2Obj(name string) string {
|
||||||
return titleCasedName(name)
|
return titleCasedName(name)
|
||||||
}
|
}
|
||||||
|
@ -168,10 +176,12 @@ func gonicCasedName(name string) string {
|
||||||
return strings.ToLower(string(newstr))
|
return strings.ToLower(string(newstr))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Obj2Table implements Mapper
|
||||||
func (mapper GonicMapper) Obj2Table(name string) string {
|
func (mapper GonicMapper) Obj2Table(name string) string {
|
||||||
return gonicCasedName(name)
|
return gonicCasedName(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Table2Obj implements Mapper
|
||||||
func (mapper GonicMapper) Table2Obj(name string) string {
|
func (mapper GonicMapper) Table2Obj(name string) string {
|
||||||
newstr := make([]rune, 0)
|
newstr := make([]rune, 0)
|
||||||
|
|
||||||
|
@ -234,14 +244,17 @@ type PrefixMapper struct {
|
||||||
Prefix string
|
Prefix string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Obj2Table implements Mapper
|
||||||
func (mapper PrefixMapper) Obj2Table(name string) string {
|
func (mapper PrefixMapper) Obj2Table(name string) string {
|
||||||
return mapper.Prefix + mapper.Mapper.Obj2Table(name)
|
return mapper.Prefix + mapper.Mapper.Obj2Table(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Table2Obj implements Mapper
|
||||||
func (mapper PrefixMapper) Table2Obj(name string) string {
|
func (mapper PrefixMapper) Table2Obj(name string) string {
|
||||||
return mapper.Mapper.Table2Obj(name[len(mapper.Prefix):])
|
return mapper.Mapper.Table2Obj(name[len(mapper.Prefix):])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewPrefixMapper creates a prefix mapper
|
||||||
func NewPrefixMapper(mapper Mapper, prefix string) PrefixMapper {
|
func NewPrefixMapper(mapper Mapper, prefix string) PrefixMapper {
|
||||||
return PrefixMapper{mapper, prefix}
|
return PrefixMapper{mapper, prefix}
|
||||||
}
|
}
|
||||||
|
@ -252,14 +265,17 @@ type SuffixMapper struct {
|
||||||
Suffix string
|
Suffix string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Obj2Table implements Mapper
|
||||||
func (mapper SuffixMapper) Obj2Table(name string) string {
|
func (mapper SuffixMapper) Obj2Table(name string) string {
|
||||||
return mapper.Mapper.Obj2Table(name) + mapper.Suffix
|
return mapper.Mapper.Obj2Table(name) + mapper.Suffix
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Table2Obj implements Mapper
|
||||||
func (mapper SuffixMapper) Table2Obj(name string) string {
|
func (mapper SuffixMapper) Table2Obj(name string) string {
|
||||||
return mapper.Mapper.Table2Obj(name[:len(name)-len(mapper.Suffix)])
|
return mapper.Mapper.Table2Obj(name[:len(name)-len(mapper.Suffix)])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewSuffixMapper creates a suffix mapper
|
||||||
func NewSuffixMapper(mapper Mapper, suffix string) SuffixMapper {
|
func NewSuffixMapper(mapper Mapper, suffix string) SuffixMapper {
|
||||||
return SuffixMapper{mapper, suffix}
|
return SuffixMapper{mapper, suffix}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ var (
|
||||||
tvCache sync.Map
|
tvCache sync.Map
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// GetTableName returns table name
|
||||||
func GetTableName(mapper Mapper, v reflect.Value) string {
|
func GetTableName(mapper Mapper, v reflect.Value) string {
|
||||||
if v.Type().Implements(tpTableName) {
|
if v.Type().Implements(tpTableName) {
|
||||||
return v.Interface().(TableName).TableName()
|
return v.Interface().(TableName).TableName()
|
||||||
|
|
|
@ -13,6 +13,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// enumerates all database mapping way
|
||||||
const (
|
const (
|
||||||
TWOSIDES = iota + 1
|
TWOSIDES = iota + 1
|
||||||
ONLYTODB
|
ONLYTODB
|
||||||
|
|
|
@ -28,6 +28,7 @@ func NewIndex(name string, indexType int) *Index {
|
||||||
return &Index{true, name, indexType, make([]string, 0)}
|
return &Index{true, name, indexType, make([]string, 0)}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// XName returns the special index name for the table
|
||||||
func (index *Index) XName(tableName string) string {
|
func (index *Index) XName(tableName string) string {
|
||||||
if !strings.HasPrefix(index.Name, "UQE_") &&
|
if !strings.HasPrefix(index.Name, "UQE_") &&
|
||||||
!strings.HasPrefix(index.Name, "IDX_") {
|
!strings.HasPrefix(index.Name, "IDX_") {
|
||||||
|
@ -43,11 +44,10 @@ func (index *Index) XName(tableName string) string {
|
||||||
|
|
||||||
// AddColumn add columns which will be composite index
|
// AddColumn add columns which will be composite index
|
||||||
func (index *Index) AddColumn(cols ...string) {
|
func (index *Index) AddColumn(cols ...string) {
|
||||||
for _, col := range cols {
|
index.Cols = append(index.Cols, cols...)
|
||||||
index.Cols = append(index.Cols, col)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Equal return true if the two Index is equal
|
||||||
func (index *Index) Equal(dst *Index) bool {
|
func (index *Index) Equal(dst *Index) bool {
|
||||||
if index.Type != dst.Type {
|
if index.Type != dst.Type {
|
||||||
return false
|
return false
|
||||||
|
|
|
@ -11,13 +11,16 @@ import (
|
||||||
"xorm.io/xorm/internal/utils"
|
"xorm.io/xorm/internal/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// PK represents primary key values
|
||||||
type PK []interface{}
|
type PK []interface{}
|
||||||
|
|
||||||
|
// NewPK creates primay keys
|
||||||
func NewPK(pks ...interface{}) *PK {
|
func NewPK(pks ...interface{}) *PK {
|
||||||
p := PK(pks)
|
p := PK(pks)
|
||||||
return &p
|
return &p
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsZero return true if primay keys are zero
|
||||||
func (p *PK) IsZero() bool {
|
func (p *PK) IsZero() bool {
|
||||||
for _, k := range *p {
|
for _, k := range *p {
|
||||||
if utils.IsZero(k) {
|
if utils.IsZero(k) {
|
||||||
|
@ -27,6 +30,7 @@ func (p *PK) IsZero() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ToString convert to SQL string
|
||||||
func (p *PK) ToString() (string, error) {
|
func (p *PK) ToString() (string, error) {
|
||||||
buf := new(bytes.Buffer)
|
buf := new(bytes.Buffer)
|
||||||
enc := gob.NewEncoder(buf)
|
enc := gob.NewEncoder(buf)
|
||||||
|
@ -34,6 +38,7 @@ func (p *PK) ToString() (string, error) {
|
||||||
return buf.String(), err
|
return buf.String(), err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FromString reads content to load primary keys
|
||||||
func (p *PK) FromString(content string) error {
|
func (p *PK) FromString(content string) error {
|
||||||
dec := gob.NewDecoder(bytes.NewBufferString(content))
|
dec := gob.NewDecoder(bytes.NewBufferString(content))
|
||||||
err := dec.Decode(p)
|
err := dec.Decode(p)
|
||||||
|
|
|
@ -16,10 +16,10 @@ type Quoter struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// AlwaysFalseReverse always think it's not a reverse word
|
// AlwaysNoReserve always think it's not a reverse word
|
||||||
AlwaysNoReserve = func(string) bool { return false }
|
AlwaysNoReserve = func(string) bool { return false }
|
||||||
|
|
||||||
// AlwaysReverse always reverse the word
|
// AlwaysReserve always reverse the word
|
||||||
AlwaysReserve = func(string) bool { return true }
|
AlwaysReserve = func(string) bool { return true }
|
||||||
|
|
||||||
// CommanQuoteMark represnets the common quote mark
|
// CommanQuoteMark represnets the common quote mark
|
||||||
|
@ -29,10 +29,12 @@ var (
|
||||||
CommonQuoter = Quoter{CommanQuoteMark, CommanQuoteMark, AlwaysReserve}
|
CommonQuoter = Quoter{CommanQuoteMark, CommanQuoteMark, AlwaysReserve}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// IsEmpty return true if no prefix and suffix
|
||||||
func (q Quoter) IsEmpty() bool {
|
func (q Quoter) IsEmpty() bool {
|
||||||
return q.Prefix == 0 && q.Suffix == 0
|
return q.Prefix == 0 && q.Suffix == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Quote quote a string
|
||||||
func (q Quoter) Quote(s string) string {
|
func (q Quoter) Quote(s string) string {
|
||||||
var buf strings.Builder
|
var buf strings.Builder
|
||||||
q.QuoteTo(&buf, s)
|
q.QuoteTo(&buf, s)
|
||||||
|
@ -59,12 +61,14 @@ func (q Quoter) Trim(s string) string {
|
||||||
return buf.String()
|
return buf.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Join joins a slice with quoters
|
||||||
func (q Quoter) Join(a []string, sep string) string {
|
func (q Quoter) Join(a []string, sep string) string {
|
||||||
var b strings.Builder
|
var b strings.Builder
|
||||||
q.JoinWrite(&b, a, sep)
|
q.JoinWrite(&b, a, sep)
|
||||||
return b.String()
|
return b.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// JoinWrite writes quoted content to a builder
|
||||||
func (q Quoter) JoinWrite(b *strings.Builder, a []string, sep string) error {
|
func (q Quoter) JoinWrite(b *strings.Builder, a []string, sep string) error {
|
||||||
if len(a) == 0 {
|
if len(a) == 0 {
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -90,23 +90,28 @@ func (table *Table) PKColumns() []*Column {
|
||||||
return columns
|
return columns
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ColumnType returns a column's type
|
||||||
func (table *Table) ColumnType(name string) reflect.Type {
|
func (table *Table) ColumnType(name string) reflect.Type {
|
||||||
t, _ := table.Type.FieldByName(name)
|
t, _ := table.Type.FieldByName(name)
|
||||||
return t.Type
|
return t.Type
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AutoIncrColumn returns autoincrement column
|
||||||
func (table *Table) AutoIncrColumn() *Column {
|
func (table *Table) AutoIncrColumn() *Column {
|
||||||
return table.GetColumn(table.AutoIncrement)
|
return table.GetColumn(table.AutoIncrement)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// VersionColumn returns version column's information
|
||||||
func (table *Table) VersionColumn() *Column {
|
func (table *Table) VersionColumn() *Column {
|
||||||
return table.GetColumn(table.Version)
|
return table.GetColumn(table.Version)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UpdatedColumn returns updated column's information
|
||||||
func (table *Table) UpdatedColumn() *Column {
|
func (table *Table) UpdatedColumn() *Column {
|
||||||
return table.GetColumn(table.Updated)
|
return table.GetColumn(table.Updated)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeletedColumn returns deleted column's information
|
||||||
func (table *Table) DeletedColumn() *Column {
|
func (table *Table) DeletedColumn() *Column {
|
||||||
return table.GetColumn(table.Deleted)
|
return table.GetColumn(table.Deleted)
|
||||||
}
|
}
|
||||||
|
|
|
@ -222,53 +222,55 @@ var (
|
||||||
|
|
||||||
// !nashtsai! treat following var as interal const values, these are used for reflect.TypeOf comparison
|
// !nashtsai! treat following var as interal const values, these are used for reflect.TypeOf comparison
|
||||||
var (
|
var (
|
||||||
c_EMPTY_STRING string
|
emptyString string
|
||||||
c_BOOL_DEFAULT bool
|
boolDefault bool
|
||||||
c_BYTE_DEFAULT byte
|
byteDefault byte
|
||||||
c_COMPLEX64_DEFAULT complex64
|
complex64Default complex64
|
||||||
c_COMPLEX128_DEFAULT complex128
|
complex128Default complex128
|
||||||
c_FLOAT32_DEFAULT float32
|
float32Default float32
|
||||||
c_FLOAT64_DEFAULT float64
|
float64Default float64
|
||||||
c_INT64_DEFAULT int64
|
int64Default int64
|
||||||
c_UINT64_DEFAULT uint64
|
uint64Default uint64
|
||||||
c_INT32_DEFAULT int32
|
int32Default int32
|
||||||
c_UINT32_DEFAULT uint32
|
uint32Default uint32
|
||||||
c_INT16_DEFAULT int16
|
int16Default int16
|
||||||
c_UINT16_DEFAULT uint16
|
uint16Default uint16
|
||||||
c_INT8_DEFAULT int8
|
int8Default int8
|
||||||
c_UINT8_DEFAULT uint8
|
uint8Default uint8
|
||||||
c_INT_DEFAULT int
|
intDefault int
|
||||||
c_UINT_DEFAULT uint
|
uintDefault uint
|
||||||
c_TIME_DEFAULT time.Time
|
timeDefault time.Time
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// enumerates all types
|
||||||
var (
|
var (
|
||||||
IntType = reflect.TypeOf(c_INT_DEFAULT)
|
IntType = reflect.TypeOf(intDefault)
|
||||||
Int8Type = reflect.TypeOf(c_INT8_DEFAULT)
|
Int8Type = reflect.TypeOf(int8Default)
|
||||||
Int16Type = reflect.TypeOf(c_INT16_DEFAULT)
|
Int16Type = reflect.TypeOf(int16Default)
|
||||||
Int32Type = reflect.TypeOf(c_INT32_DEFAULT)
|
Int32Type = reflect.TypeOf(int32Default)
|
||||||
Int64Type = reflect.TypeOf(c_INT64_DEFAULT)
|
Int64Type = reflect.TypeOf(int64Default)
|
||||||
|
|
||||||
UintType = reflect.TypeOf(c_UINT_DEFAULT)
|
UintType = reflect.TypeOf(uintDefault)
|
||||||
Uint8Type = reflect.TypeOf(c_UINT8_DEFAULT)
|
Uint8Type = reflect.TypeOf(uint8Default)
|
||||||
Uint16Type = reflect.TypeOf(c_UINT16_DEFAULT)
|
Uint16Type = reflect.TypeOf(uint16Default)
|
||||||
Uint32Type = reflect.TypeOf(c_UINT32_DEFAULT)
|
Uint32Type = reflect.TypeOf(uint32Default)
|
||||||
Uint64Type = reflect.TypeOf(c_UINT64_DEFAULT)
|
Uint64Type = reflect.TypeOf(uint64Default)
|
||||||
|
|
||||||
Float32Type = reflect.TypeOf(c_FLOAT32_DEFAULT)
|
Float32Type = reflect.TypeOf(float32Default)
|
||||||
Float64Type = reflect.TypeOf(c_FLOAT64_DEFAULT)
|
Float64Type = reflect.TypeOf(float64Default)
|
||||||
|
|
||||||
Complex64Type = reflect.TypeOf(c_COMPLEX64_DEFAULT)
|
Complex64Type = reflect.TypeOf(complex64Default)
|
||||||
Complex128Type = reflect.TypeOf(c_COMPLEX128_DEFAULT)
|
Complex128Type = reflect.TypeOf(complex128Default)
|
||||||
|
|
||||||
StringType = reflect.TypeOf(c_EMPTY_STRING)
|
StringType = reflect.TypeOf(emptyString)
|
||||||
BoolType = reflect.TypeOf(c_BOOL_DEFAULT)
|
BoolType = reflect.TypeOf(boolDefault)
|
||||||
ByteType = reflect.TypeOf(c_BYTE_DEFAULT)
|
ByteType = reflect.TypeOf(byteDefault)
|
||||||
BytesType = reflect.SliceOf(ByteType)
|
BytesType = reflect.SliceOf(ByteType)
|
||||||
|
|
||||||
TimeType = reflect.TypeOf(c_TIME_DEFAULT)
|
TimeType = reflect.TypeOf(timeDefault)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// enumerates all types
|
||||||
var (
|
var (
|
||||||
PtrIntType = reflect.PtrTo(IntType)
|
PtrIntType = reflect.PtrTo(IntType)
|
||||||
PtrInt8Type = reflect.PtrTo(Int8Type)
|
PtrInt8Type = reflect.PtrTo(Int8Type)
|
||||||
|
@ -313,7 +315,7 @@ func Type2SQLType(t reflect.Type) (st SQLType) {
|
||||||
case reflect.Complex64, reflect.Complex128:
|
case reflect.Complex64, reflect.Complex128:
|
||||||
st = SQLType{Varchar, 64, 0}
|
st = SQLType{Varchar, 64, 0}
|
||||||
case reflect.Array, reflect.Slice, reflect.Map:
|
case reflect.Array, reflect.Slice, reflect.Map:
|
||||||
if t.Elem() == reflect.TypeOf(c_BYTE_DEFAULT) {
|
if t.Elem() == reflect.TypeOf(byteDefault) {
|
||||||
st = SQLType{Blob, 0, 0}
|
st = SQLType{Blob, 0, 0}
|
||||||
} else {
|
} else {
|
||||||
st = SQLType{Text, 0, 0}
|
st = SQLType{Text, 0, 0}
|
||||||
|
@ -337,7 +339,7 @@ func Type2SQLType(t reflect.Type) (st SQLType) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// default sql type change to go types
|
// SQLType2Type convert default sql type change to go types
|
||||||
func SQLType2Type(st SQLType) reflect.Type {
|
func SQLType2Type(st SQLType) reflect.Type {
|
||||||
name := strings.ToUpper(st.Name)
|
name := strings.ToUpper(st.Name)
|
||||||
switch name {
|
switch name {
|
||||||
|
@ -356,7 +358,7 @@ func SQLType2Type(st SQLType) reflect.Type {
|
||||||
case Bool:
|
case Bool:
|
||||||
return reflect.TypeOf(true)
|
return reflect.TypeOf(true)
|
||||||
case DateTime, Date, Time, TimeStamp, TimeStampz, SmallDateTime, Year:
|
case DateTime, Date, Time, TimeStamp, TimeStampz, SmallDateTime, Year:
|
||||||
return reflect.TypeOf(c_TIME_DEFAULT)
|
return reflect.TypeOf(timeDefault)
|
||||||
case Decimal, Numeric, Money, SmallMoney:
|
case Decimal, Numeric, Money, SmallMoney:
|
||||||
return reflect.TypeOf("")
|
return reflect.TypeOf("")
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -21,9 +21,11 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
// ErrUnsupportedType represents an unsupported type error
|
||||||
ErrUnsupportedType = errors.New("Unsupported type")
|
ErrUnsupportedType = errors.New("Unsupported type")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Parser represents a parser for xorm tag
|
||||||
type Parser struct {
|
type Parser struct {
|
||||||
identifier string
|
identifier string
|
||||||
dialect dialects.Dialect
|
dialect dialects.Dialect
|
||||||
|
@ -34,6 +36,7 @@ type Parser struct {
|
||||||
tableCache sync.Map // map[reflect.Type]*schemas.Table
|
tableCache sync.Map // map[reflect.Type]*schemas.Table
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewParser creates a tag parser
|
||||||
func NewParser(identifier string, dialect dialects.Dialect, tableMapper, columnMapper names.Mapper, cacherMgr *caches.Manager) *Parser {
|
func NewParser(identifier string, dialect dialects.Dialect, tableMapper, columnMapper names.Mapper, cacherMgr *caches.Manager) *Parser {
|
||||||
return &Parser{
|
return &Parser{
|
||||||
identifier: identifier,
|
identifier: identifier,
|
||||||
|
@ -45,29 +48,35 @@ func NewParser(identifier string, dialect dialects.Dialect, tableMapper, columnM
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetTableMapper returns table mapper
|
||||||
func (parser *Parser) GetTableMapper() names.Mapper {
|
func (parser *Parser) GetTableMapper() names.Mapper {
|
||||||
return parser.tableMapper
|
return parser.tableMapper
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetTableMapper sets table mapper
|
||||||
func (parser *Parser) SetTableMapper(mapper names.Mapper) {
|
func (parser *Parser) SetTableMapper(mapper names.Mapper) {
|
||||||
parser.ClearCaches()
|
parser.ClearCaches()
|
||||||
parser.tableMapper = mapper
|
parser.tableMapper = mapper
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetColumnMapper returns column mapper
|
||||||
func (parser *Parser) GetColumnMapper() names.Mapper {
|
func (parser *Parser) GetColumnMapper() names.Mapper {
|
||||||
return parser.columnMapper
|
return parser.columnMapper
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetColumnMapper sets column mapper
|
||||||
func (parser *Parser) SetColumnMapper(mapper names.Mapper) {
|
func (parser *Parser) SetColumnMapper(mapper names.Mapper) {
|
||||||
parser.ClearCaches()
|
parser.ClearCaches()
|
||||||
parser.columnMapper = mapper
|
parser.columnMapper = mapper
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetIdentifier sets tag identifier
|
||||||
func (parser *Parser) SetIdentifier(identifier string) {
|
func (parser *Parser) SetIdentifier(identifier string) {
|
||||||
parser.ClearCaches()
|
parser.ClearCaches()
|
||||||
parser.identifier = identifier
|
parser.identifier = identifier
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ParseWithCache parse a struct with cache
|
||||||
func (parser *Parser) ParseWithCache(v reflect.Value) (*schemas.Table, error) {
|
func (parser *Parser) ParseWithCache(v reflect.Value) (*schemas.Table, error) {
|
||||||
t := v.Type()
|
t := v.Type()
|
||||||
tableI, ok := parser.tableCache.Load(t)
|
tableI, ok := parser.tableCache.Load(t)
|
||||||
|
|
Loading…
Reference in New Issue