|
|
|
@ -61,10 +61,6 @@ func (engine *Engine) setCacher(tableName string, cacher core.Cacher) {
|
|
|
|
|
engine.cacherLock.Unlock()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (engine *Engine) SetCacher(tableName string, cacher core.Cacher) {
|
|
|
|
|
engine.setCacher(tableName, cacher)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (engine *Engine) getCacher(tableName string) core.Cacher {
|
|
|
|
|
var cacher core.Cacher
|
|
|
|
|
var ok bool
|
|
|
|
@ -77,10 +73,6 @@ func (engine *Engine) getCacher(tableName string) core.Cacher {
|
|
|
|
|
return cacher
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (engine *Engine) GetCacher(tableName string) core.Cacher {
|
|
|
|
|
return engine.getCacher(tableName)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// BufferSize sets buffer size for iterate
|
|
|
|
|
func (engine *Engine) BufferSize(size int) *Session {
|
|
|
|
|
session := engine.NewSession()
|
|
|
|
@ -126,11 +118,6 @@ func (engine *Engine) ShowExecTime(show ...bool) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Logger return the logger interface
|
|
|
|
|
func (engine *Engine) Logger() core.ILogger {
|
|
|
|
|
return engine.logger
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// SetLogger set the new logger
|
|
|
|
|
func (engine *Engine) SetLogger(logger core.ILogger) {
|
|
|
|
|
engine.logger = logger
|
|
|
|
@ -138,18 +125,6 @@ func (engine *Engine) SetLogger(logger core.ILogger) {
|
|
|
|
|
engine.dialect.SetLogger(logger)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// SetLogLevel sets the logger level
|
|
|
|
|
func (engine *Engine) SetLogLevel(level core.LogLevel) {
|
|
|
|
|
engine.logger.SetLevel(level)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// SetDisableGlobalCache disable global cache or not
|
|
|
|
|
func (engine *Engine) SetDisableGlobalCache(disable bool) {
|
|
|
|
|
if engine.disableGlobalCache != disable {
|
|
|
|
|
engine.disableGlobalCache = disable
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// DriverName return the current sql driver's name
|
|
|
|
|
func (engine *Engine) DriverName() string {
|
|
|
|
|
return engine.dialect.DriverName()
|
|
|
|
@ -300,11 +275,6 @@ func (engine *Engine) SetDefaultCacher(cacher core.Cacher) {
|
|
|
|
|
engine.Cacher = cacher
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// GetDefaultCacher returns the default cacher
|
|
|
|
|
func (engine *Engine) GetDefaultCacher() core.Cacher {
|
|
|
|
|
return engine.Cacher
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// NoCache If you has set default cacher, and you want temporilly stop use cache,
|
|
|
|
|
// you can use NoCache()
|
|
|
|
|
func (engine *Engine) NoCache() *Session {
|
|
|
|
@ -320,12 +290,6 @@ func (engine *Engine) NoCascade() *Session {
|
|
|
|
|
return session.NoCascade()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// MapCacher Set a table use a special cacher
|
|
|
|
|
func (engine *Engine) MapCacher(bean interface{}, cacher core.Cacher) error {
|
|
|
|
|
engine.setCacher(engine.TableName(bean, true), cacher)
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// NewDB provides an interface to operate database directly
|
|
|
|
|
func (engine *Engine) NewDB() (*core.DB, error) {
|
|
|
|
|
return core.OpenDialect(engine.dialect)
|
|
|
|
@ -426,7 +390,7 @@ func (engine *Engine) loadTableInfo(table *core.Table) error {
|
|
|
|
|
if col := table.GetColumn(name); col != nil {
|
|
|
|
|
col.Indexes[index.Name] = index.Type
|
|
|
|
|
} else {
|
|
|
|
|
return fmt.Errorf("Unknown col %s in index %v of table %v, columns %v", name, index.Name, table.Name, table.ColumnsSeq())
|
|
|
|
|
return fmt.Errorf("unknown col %s in index %v of table %v, columns %v", name, index.Name, table.Name, table.ColumnsSeq())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -448,177 +412,6 @@ func (engine *Engine) DBMetas() ([]*core.Table, error) {
|
|
|
|
|
return tables, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// DumpAllToFile dump database all table structs and data to a file
|
|
|
|
|
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, tp...)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// DumpAll dump database all table structs and data to w
|
|
|
|
|
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.
|
|
|
|
|
func (engine *Engine) DumpTablesToFile(tables []*core.Table, fp string, tp ...core.DbType) error {
|
|
|
|
|
f, err := os.Create(fp)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
defer f.Close()
|
|
|
|
|
return engine.DumpTables(tables, f, tp...)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// DumpTables dump specify tables to io.Writer
|
|
|
|
|
func (engine *Engine) DumpTables(tables []*core.Table, w io.Writer, tp ...core.DbType) error {
|
|
|
|
|
return engine.dumpTables(tables, w, tp...)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 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
|
|
|
|
|
if len(tp) == 0 {
|
|
|
|
|
dialect = engine.dialect
|
|
|
|
|
distDBName = string(engine.dialect.DBType())
|
|
|
|
|
} else {
|
|
|
|
|
dialect = core.QueryDialect(tp[0])
|
|
|
|
|
if dialect == nil {
|
|
|
|
|
return errors.New("Unsupported database type")
|
|
|
|
|
}
|
|
|
|
|
dialect.Init(nil, engine.dialect.URI(), "", "")
|
|
|
|
|
distDBName = string(tp[0])
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_, err := io.WriteString(w, fmt.Sprintf("/*Generated by xorm v%s %s, from %s to %s*/\n\n",
|
|
|
|
|
Version, time.Now().In(engine.TZLocation).Format("2006-01-02 15:04:05"), engine.dialect.DBType(), strings.ToUpper(distDBName)))
|
|
|
|
|
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
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cols := table.ColumnsSeq()
|
|
|
|
|
colNames := engine.dialect.Quote(strings.Join(cols, engine.dialect.Quote(", ")))
|
|
|
|
|
destColNames := dialect.Quote(strings.Join(cols, dialect.Quote(", ")))
|
|
|
|
|
|
|
|
|
|
rows, err := engine.DB().Query("SELECT " + colNames + " FROM " + engine.Quote(table.Name))
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
defer rows.Close()
|
|
|
|
|
|
|
|
|
|
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)+" ("+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")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if d == nil {
|
|
|
|
|
temp += ", NULL"
|
|
|
|
|
} else if col.SQLType.IsText() || col.SQLType.IsTime() {
|
|
|
|
|
var v = fmt.Sprintf("%s", d)
|
|
|
|
|
if strings.HasSuffix(v, " +0000 UTC") {
|
|
|
|
|
temp += fmt.Sprintf(", '%s'", v[0:len(v)-len(" +0000 UTC")])
|
|
|
|
|
} else {
|
|
|
|
|
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:
|
|
|
|
|
if col.SQLType.Name == core.Bool {
|
|
|
|
|
temp += fmt.Sprintf(", %v", strconv.FormatBool(d.([]byte)[0] != byte('0')))
|
|
|
|
|
} else {
|
|
|
|
|
temp += fmt.Sprintf(", %s", string(d.([]byte)))
|
|
|
|
|
}
|
|
|
|
|
case reflect.Int16, reflect.Int8, reflect.Int32, reflect.Int64, reflect.Int:
|
|
|
|
|
if col.SQLType.Name == core.Bool {
|
|
|
|
|
temp += fmt.Sprintf(", %v", strconv.FormatBool(reflect.ValueOf(d).Int() > 0))
|
|
|
|
|
} else {
|
|
|
|
|
temp += fmt.Sprintf(", %v", d)
|
|
|
|
|
}
|
|
|
|
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
|
|
|
|
if col.SQLType.Name == core.Bool {
|
|
|
|
|
temp += fmt.Sprintf(", %v", strconv.FormatBool(reflect.ValueOf(d).Uint() > 0))
|
|
|
|
|
} else {
|
|
|
|
|
temp += fmt.Sprintf(", %v", d)
|
|
|
|
|
}
|
|
|
|
|
default:
|
|
|
|
|
temp += fmt.Sprintf(", %v", d)
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
s := fmt.Sprintf("%v", d)
|
|
|
|
|
if strings.Contains(s, ":") || strings.Contains(s, "-") {
|
|
|
|
|
if strings.HasSuffix(s, " +0000 UTC") {
|
|
|
|
|
temp += fmt.Sprintf(", '%s'", s[0:len(s)-len(" +0000 UTC")])
|
|
|
|
|
} else {
|
|
|
|
|
temp += fmt.Sprintf(", '%s'", s)
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
temp += fmt.Sprintf(", %s", s)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
_, err = io.WriteString(w, temp[2:]+");\n")
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// FIXME: Hack for postgres
|
|
|
|
|
if string(dialect.DBType()) == core.POSTGRES && table.AutoIncrColumn() != nil {
|
|
|
|
|
_, err = io.WriteString(w, "SELECT setval('"+table.Name+"_id_seq', COALESCE((SELECT MAX("+table.AutoIncrColumn().Name+") + 1 FROM "+dialect.Quote(table.Name)+"), 1), false);\n")
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Cascade use cascade or not
|
|
|
|
|
func (engine *Engine) Cascade(trueOrFalse ...bool) *Session {
|
|
|
|
|
session := engine.NewSession()
|
|
|
|
@ -894,16 +687,6 @@ func (t *Table) IsValid() bool {
|
|
|
|
|
return t.Table != nil && len(t.Name) > 0
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TableInfo get table info according to bean's content
|
|
|
|
|
func (engine *Engine) TableInfo(bean interface{}) *Table {
|
|
|
|
|
v := rValue(bean)
|
|
|
|
|
tb, err := engine.autoMapType(v)
|
|
|
|
|
if err != nil {
|
|
|
|
|
engine.logger.Error(err)
|
|
|
|
|
}
|
|
|
|
|
return &Table{tb, engine.TableName(bean)}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func addIndex(indexName string, table *core.Table, col *core.Column, indexType int) {
|
|
|
|
|
if index, ok := table.Indexes[indexName]; ok {
|
|
|
|
|
index.AddColumn(col.Name)
|
|
|
|
@ -1230,30 +1013,6 @@ func (engine *Engine) CreateUniques(bean interface{}) error {
|
|
|
|
|
return session.CreateUniques(bean)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ClearCacheBean if enabled cache, clear the cache bean
|
|
|
|
|
func (engine *Engine) ClearCacheBean(bean interface{}, id string) error {
|
|
|
|
|
tableName := engine.TableName(bean)
|
|
|
|
|
cacher := engine.getCacher(tableName)
|
|
|
|
|
if cacher != nil {
|
|
|
|
|
cacher.ClearIds(tableName)
|
|
|
|
|
cacher.DelBean(tableName, id)
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ClearCache if enabled cache, clear some tables' cache
|
|
|
|
|
func (engine *Engine) ClearCache(beans ...interface{}) error {
|
|
|
|
|
for _, bean := range beans {
|
|
|
|
|
tableName := engine.TableName(bean)
|
|
|
|
|
cacher := engine.getCacher(tableName)
|
|
|
|
|
if cacher != nil {
|
|
|
|
|
cacher.ClearIds(tableName)
|
|
|
|
|
cacher.ClearBeans(tableName)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Sync the new struct changes to database, this method will automatically add
|
|
|
|
|
// table, column, index, unique. but will not delete or change anything.
|
|
|
|
|
// If you change some field, you should change the database manually.
|
|
|
|
@ -1279,10 +1038,7 @@ func (engine *Engine) Sync(beans ...interface{}) error {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/*isEmpty, err := engine.IsEmptyTable(bean)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}*/
|
|
|
|
|
|
|
|
|
|
var isEmpty bool
|
|
|
|
|
if isEmpty {
|
|
|
|
|
err = session.dropTable(bean)
|
|
|
|
|