Merge pull request 'master' (#1) from xorm/xorm:master into master

Reviewed-on: https://gitea.com/janse_zyd/xorm/pulls/1
This commit is contained in:
janse_zyd 2021-06-02 17:02:08 +08:00
commit 9d0d697b2a
4 changed files with 134 additions and 34 deletions

View File

@ -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

View File

@ -243,4 +243,4 @@ test-tidb\#%: go-check
.PHONY: vet .PHONY: vet
vet: vet:
$(GO) vet $(shell $(GO) list ./...) $(GO) vet $(shell $(GO) list ./...)

View File

@ -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
View File

@ -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
} }