master #1
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
|
||||||
|
@ -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 {
|
||||||
|
106
engine.go
106
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,6 +619,52 @@ func (engine *Engine) dumpTables(tables []*schemas.Table, w io.Writer, tp ...sch
|
|||||||
}
|
}
|
||||||
defer rows.Close()
|
defer rows.Close()
|
||||||
|
|
||||||
|
if table.Type != nil {
|
||||||
|
sess := engine.NewSession()
|
||||||
|
defer sess.Close()
|
||||||
|
for rows.Next() {
|
||||||
|
beanValue := reflect.New(table.Type)
|
||||||
|
bean := beanValue.Interface()
|
||||||
|
fields, err := rows.Columns()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
scanResults, err := sess.row2Slice(rows, fields, bean)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
dataStruct := utils.ReflectValue(bean)
|
||||||
|
_, 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
dest := make([]interface{}, len(cols))
|
dest := make([]interface{}, len(cols))
|
||||||
err = rows.ScanSlice(&dest)
|
err = rows.ScanSlice(&dest)
|
||||||
@ -594,7 +672,7 @@ func (engine *Engine) dumpTables(tables []*schemas.Table, w io.Writer, tp ...sch
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = io.WriteString(w, "INSERT INTO "+dstDialect.Quoter().Quote(tableName)+" ("+destColNames+") VALUES (")
|
_, err = io.WriteString(w, "INSERT INTO "+dstDialect.Quoter().Quote(dstTableName)+" ("+destColNames+") VALUES (")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -605,6 +683,7 @@ func (engine *Engine) dumpTables(tables []*schemas.Table, w io.Writer, tp ...sch
|
|||||||
if col == nil {
|
if col == nil {
|
||||||
return errors.New("unknow column error")
|
return errors.New("unknow column error")
|
||||||
}
|
}
|
||||||
|
|
||||||
temp += "," + formatColumnValue(dstDialect, d, col)
|
temp += "," + formatColumnValue(dstDialect, d, col)
|
||||||
}
|
}
|
||||||
_, err = io.WriteString(w, temp[1:]+");\n")
|
_, err = io.WriteString(w, temp[1:]+");\n")
|
||||||
@ -612,10 +691,11 @@ func (engine *Engine) dumpTables(tables []*schemas.Table, w io.Writer, tp ...sch
|
|||||||
return err
|
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
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user