From b1bbae394904aa5dc5e7a69ca8d88199b729e547 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Wed, 18 Jan 2017 20:14:20 +0800 Subject: [PATCH] Let DumpAll support dump to another database --- engine.go | 176 +++++++++++------------------------------------------- 1 file changed, 36 insertions(+), 140 deletions(-) diff --git a/engine.go b/engine.go index 98ce943c..cc0c7926 100644 --- a/engine.go +++ b/engine.go @@ -348,8 +348,6 @@ func (engine *Engine) DBMetas() ([]*core.Table, error) { for _, name := range colSeq { table.AddColumn(cols[name]) } - //table.Columns = cols - //table.ColumnsSeq = colSeq indexes, err := engine.dialect.GetIndexes(table.Name) if err != nil { return nil, err @@ -370,18 +368,22 @@ func (engine *Engine) DBMetas() ([]*core.Table, error) { } // DumpAllToFile dump database all table structs and data to a file -func (engine *Engine) DumpAllToFile(fp string) error { +func (engine *Engine) DumpAllToFile(fp string, tp ...core.DbType) error { f, err := os.Create(fp) if err != nil { return err } defer f.Close() - return engine.DumpAll(f) + return engine.DumpAll(f, tp...) } // DumpAll dump database all table structs and data to w -func (engine *Engine) DumpAll(w io.Writer) error { - return engine.dumpAll(w, engine.dialect.DBType()) +func (engine *Engine) DumpAll(w io.Writer, tp ...core.DbType) error { + tables, err := engine.DBMetas() + if err != nil { + return err + } + return engine.DumpTables(tables, w, tp...) } // DumpTablesToFile dump specified tables to SQL file. @@ -399,140 +401,7 @@ func (engine *Engine) DumpTables(tables []*core.Table, w io.Writer, tp ...core.D return engine.dumpTables(tables, w, tp...) } -func (engine *Engine) tableName(beanOrTableName interface{}) (string, error) { - v := rValue(beanOrTableName) - if v.Type().Kind() == reflect.String { - return beanOrTableName.(string), nil - } else if v.Type().Kind() == reflect.Struct { - return engine.tbName(v), nil - } - return "", errors.New("bean should be a struct or struct's point") -} - -func (engine *Engine) tbName(v reflect.Value) string { - if tb, ok := v.Interface().(TableName); ok { - return tb.TableName() - } - - if v.Type().Kind() == reflect.Ptr { - if tb, ok := reflect.Indirect(v).Interface().(TableName); ok { - return tb.TableName() - } - } else if v.CanAddr() { - if tb, ok := v.Addr().Interface().(TableName); ok { - return tb.TableName() - } - } - return engine.TableMapper.Obj2Table(reflect.Indirect(v).Type().Name()) -} - -// DumpAll dump database all table structs and data to w with specify db type -func (engine *Engine) dumpAll(w io.Writer, tp ...core.DbType) error { - tables, err := engine.DBMetas() - if err != nil { - return err - } - - var dialect core.Dialect - if len(tp) == 0 { - dialect = engine.dialect - } else { - dialect = core.QueryDialect(tp[0]) - if dialect == nil { - return errors.New("Unsupported database type") - } - dialect.Init(nil, engine.dialect.URI(), "", "") - } - - _, err = io.WriteString(w, fmt.Sprintf("/*Generated by xorm v%s %s*/\n\n", - Version, time.Now().In(engine.TZLocation).Format("2006-01-02 15:04:05"))) - if err != nil { - return err - } - - for i, table := range tables { - if i > 0 { - _, err = io.WriteString(w, "\n") - if err != nil { - return err - } - } - _, err = io.WriteString(w, dialect.CreateTableSql(table, "", table.StoreEngine, "")+";\n") - if err != nil { - return err - } - for _, index := range table.Indexes { - _, err = io.WriteString(w, dialect.CreateIndexSql(table.Name, index)+";\n") - if err != nil { - return err - } - } - - rows, err := engine.DB().Query("SELECT * FROM " + engine.Quote(table.Name)) - if err != nil { - return err - } - defer rows.Close() - - cols, err := rows.Columns() - if err != nil { - return err - } - if len(cols) == 0 { - continue - } - for rows.Next() { - dest := make([]interface{}, len(cols)) - err = rows.ScanSlice(&dest) - if err != nil { - return err - } - - _, err = io.WriteString(w, "INSERT INTO "+dialect.Quote(table.Name)+" ("+dialect.Quote(strings.Join(cols, dialect.Quote(", ")))+") VALUES (") - if err != nil { - return err - } - - var temp string - for i, d := range dest { - col := table.GetColumn(cols[i]) - if d == nil { - temp += ", NULL" - } else if col.SQLType.IsText() || col.SQLType.IsTime() { - var v = fmt.Sprintf("%s", d) - temp += ", '" + strings.Replace(v, "'", "''", -1) + "'" - } else if col.SQLType.IsBlob() { - if reflect.TypeOf(d).Kind() == reflect.Slice { - temp += fmt.Sprintf(", %s", dialect.FormatBytes(d.([]byte))) - } else if reflect.TypeOf(d).Kind() == reflect.String { - temp += fmt.Sprintf(", '%s'", d.(string)) - } - } else if col.SQLType.IsNumeric() { - switch reflect.TypeOf(d).Kind() { - case reflect.Slice: - temp += fmt.Sprintf(", %s", string(d.([]byte))) - default: - temp += fmt.Sprintf(", %v", d) - } - } else { - s := fmt.Sprintf("%v", d) - if strings.Contains(s, ":") || strings.Contains(s, "-") { - temp += fmt.Sprintf(", '%s'", s) - } else { - temp += fmt.Sprintf(", %s", s) - } - } - } - _, err = io.WriteString(w, temp[2:]+");\n") - if err != nil { - return err - } - } - } - return nil -} - -// DumpAll dump database all table structs and data to w with specify db type +// dumpTables dump database all table structs and data to w with specify db type func (engine *Engine) dumpTables(tables []*core.Table, w io.Writer, tp ...core.DbType) error { var dialect core.Dialect var distDBName string @@ -644,6 +513,33 @@ func (engine *Engine) dumpTables(tables []*core.Table, w io.Writer, tp ...core.D return nil } +func (engine *Engine) tableName(beanOrTableName interface{}) (string, error) { + v := rValue(beanOrTableName) + if v.Type().Kind() == reflect.String { + return beanOrTableName.(string), nil + } else if v.Type().Kind() == reflect.Struct { + return engine.tbName(v), nil + } + return "", errors.New("bean should be a struct or struct's point") +} + +func (engine *Engine) tbName(v reflect.Value) string { + if tb, ok := v.Interface().(TableName); ok { + return tb.TableName() + } + + if v.Type().Kind() == reflect.Ptr { + if tb, ok := reflect.Indirect(v).Interface().(TableName); ok { + return tb.TableName() + } + } else if v.CanAddr() { + if tb, ok := v.Addr().Interface().(TableName); ok { + return tb.TableName() + } + } + return engine.TableMapper.Obj2Table(reflect.Indirect(v).Type().Name()) +} + // Cascade use cascade or not func (engine *Engine) Cascade(trueOrFalse ...bool) *Session { session := engine.NewSession()