github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/go-xorm/core/dialect.go (about)

     1  package core
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  	"time"
     7  )
     8  
     9  type DbType string
    10  
    11  type Uri struct {
    12  	DbType  DbType
    13  	Proto   string
    14  	Host    string
    15  	Port    string
    16  	DbName  string
    17  	User    string
    18  	Passwd  string
    19  	Charset string
    20  	Laddr   string
    21  	Raddr   string
    22  	Timeout time.Duration
    23  	Schema  string
    24  }
    25  
    26  // a dialect is a driver's wrapper
    27  type Dialect interface {
    28  	SetLogger(logger ILogger)
    29  	Init(*DB, *Uri, string, string) error
    30  	URI() *Uri
    31  	DB() *DB
    32  	DBType() DbType
    33  	SqlType(*Column) string
    34  	FormatBytes(b []byte) string
    35  
    36  	DriverName() string
    37  	DataSourceName() string
    38  
    39  	QuoteStr() string
    40  	IsReserved(string) bool
    41  	Quote(string) string
    42  	AndStr() string
    43  	OrStr() string
    44  	EqStr() string
    45  	RollBackStr() string
    46  	AutoIncrStr() string
    47  
    48  	SupportInsertMany() bool
    49  	SupportEngine() bool
    50  	SupportCharset() bool
    51  	SupportDropIfExists() bool
    52  	IndexOnTable() bool
    53  	ShowCreateNull() bool
    54  
    55  	IndexCheckSql(tableName, idxName string) (string, []interface{})
    56  	TableCheckSql(tableName string) (string, []interface{})
    57  
    58  	IsColumnExist(tableName string, colName string) (bool, error)
    59  
    60  	CreateTableSql(table *Table, tableName, storeEngine, charset string) string
    61  	DropTableSql(tableName string) string
    62  	CreateIndexSql(tableName string, index *Index) string
    63  	DropIndexSql(tableName string, index *Index) string
    64  
    65  	ModifyColumnSql(tableName string, col *Column) string
    66  
    67  	ForUpdateSql(query string) string
    68  
    69  	//CreateTableIfNotExists(table *Table, tableName, storeEngine, charset string) error
    70  	//MustDropTable(tableName string) error
    71  
    72  	GetColumns(tableName string) ([]string, map[string]*Column, error)
    73  	GetTables() ([]*Table, error)
    74  	GetIndexes(tableName string) (map[string]*Index, error)
    75  
    76  	Filters() []Filter
    77  }
    78  
    79  func OpenDialect(dialect Dialect) (*DB, error) {
    80  	return Open(dialect.DriverName(), dialect.DataSourceName())
    81  }
    82  
    83  type Base struct {
    84  	db             *DB
    85  	dialect        Dialect
    86  	driverName     string
    87  	dataSourceName string
    88  	logger         ILogger
    89  	*Uri
    90  }
    91  
    92  func (b *Base) DB() *DB {
    93  	return b.db
    94  }
    95  
    96  func (b *Base) SetLogger(logger ILogger) {
    97  	b.logger = logger
    98  }
    99  
   100  func (b *Base) Init(db *DB, dialect Dialect, uri *Uri, drivername, dataSourceName string) error {
   101  	b.db, b.dialect, b.Uri = db, dialect, uri
   102  	b.driverName, b.dataSourceName = drivername, dataSourceName
   103  	return nil
   104  }
   105  
   106  func (b *Base) URI() *Uri {
   107  	return b.Uri
   108  }
   109  
   110  func (b *Base) DBType() DbType {
   111  	return b.Uri.DbType
   112  }
   113  
   114  func (b *Base) FormatBytes(bs []byte) string {
   115  	return fmt.Sprintf("0x%x", bs)
   116  }
   117  
   118  func (b *Base) DriverName() string {
   119  	return b.driverName
   120  }
   121  
   122  func (b *Base) ShowCreateNull() bool {
   123  	return true
   124  }
   125  
   126  func (b *Base) DataSourceName() string {
   127  	return b.dataSourceName
   128  }
   129  
   130  func (b *Base) AndStr() string {
   131  	return "AND"
   132  }
   133  
   134  func (b *Base) OrStr() string {
   135  	return "OR"
   136  }
   137  
   138  func (b *Base) EqStr() string {
   139  	return "="
   140  }
   141  
   142  func (db *Base) RollBackStr() string {
   143  	return "ROLL BACK"
   144  }
   145  
   146  func (db *Base) SupportDropIfExists() bool {
   147  	return true
   148  }
   149  
   150  func (db *Base) DropTableSql(tableName string) string {
   151  	return fmt.Sprintf("DROP TABLE IF EXISTS `%s`", tableName)
   152  }
   153  
   154  func (db *Base) HasRecords(query string, args ...interface{}) (bool, error) {
   155  	db.LogSQL(query, args)
   156  	rows, err := db.DB().Query(query, args...)
   157  	if err != nil {
   158  		return false, err
   159  	}
   160  	defer rows.Close()
   161  
   162  	if rows.Next() {
   163  		return true, nil
   164  	}
   165  	return false, nil
   166  }
   167  
   168  func (db *Base) IsColumnExist(tableName, colName string) (bool, error) {
   169  	query := "SELECT `COLUMN_NAME` FROM `INFORMATION_SCHEMA`.`COLUMNS` WHERE `TABLE_SCHEMA` = ? AND `TABLE_NAME` = ? AND `COLUMN_NAME` = ?"
   170  	query = strings.Replace(query, "`", db.dialect.QuoteStr(), -1)
   171  	return db.HasRecords(query, db.DbName, tableName, colName)
   172  }
   173  
   174  /*
   175  func (db *Base) CreateTableIfNotExists(table *Table, tableName, storeEngine, charset string) error {
   176  	sql, args := db.dialect.TableCheckSql(tableName)
   177  	rows, err := db.DB().Query(sql, args...)
   178  	if db.Logger != nil {
   179  		db.Logger.Info("[sql]", sql, args)
   180  	}
   181  	if err != nil {
   182  		return err
   183  	}
   184  	defer rows.Close()
   185  
   186  	if rows.Next() {
   187  		return nil
   188  	}
   189  
   190  	sql = db.dialect.CreateTableSql(table, tableName, storeEngine, charset)
   191  	_, err = db.DB().Exec(sql)
   192  	if db.Logger != nil {
   193  		db.Logger.Info("[sql]", sql)
   194  	}
   195  	return err
   196  }*/
   197  
   198  func (db *Base) CreateIndexSql(tableName string, index *Index) string {
   199  	quote := db.dialect.Quote
   200  	var unique string
   201  	var idxName string
   202  	if index.Type == UniqueType {
   203  		unique = " UNIQUE"
   204  	}
   205  	idxName = index.XName(tableName)
   206  	return fmt.Sprintf("CREATE%s INDEX %v ON %v (%v)", unique,
   207  		quote(idxName), quote(tableName),
   208  		quote(strings.Join(index.Cols, quote(","))))
   209  }
   210  
   211  func (db *Base) DropIndexSql(tableName string, index *Index) string {
   212  	quote := db.dialect.Quote
   213  	var name string
   214  	if index.IsRegular {
   215  		name = index.XName(tableName)
   216  	} else {
   217  		name = index.Name
   218  	}
   219  	return fmt.Sprintf("DROP INDEX %v ON %s", quote(name), quote(tableName))
   220  }
   221  
   222  func (db *Base) ModifyColumnSql(tableName string, col *Column) string {
   223  	return fmt.Sprintf("alter table %s MODIFY COLUMN %s", tableName, col.StringNoPk(db.dialect))
   224  }
   225  
   226  func (b *Base) CreateTableSql(table *Table, tableName, storeEngine, charset string) string {
   227  	var sql string
   228  	sql = "CREATE TABLE IF NOT EXISTS "
   229  	if tableName == "" {
   230  		tableName = table.Name
   231  	}
   232  
   233  	sql += b.dialect.Quote(tableName)
   234  	sql += " ("
   235  
   236  	if len(table.ColumnsSeq()) > 0 {
   237  		pkList := table.PrimaryKeys
   238  
   239  		for _, colName := range table.ColumnsSeq() {
   240  			col := table.GetColumn(colName)
   241  			if col.IsPrimaryKey && len(pkList) == 1 {
   242  				sql += col.String(b.dialect)
   243  			} else {
   244  				sql += col.StringNoPk(b.dialect)
   245  			}
   246  			sql = strings.TrimSpace(sql)
   247  			sql += ", "
   248  		}
   249  
   250  		if len(pkList) > 1 {
   251  			sql += "PRIMARY KEY ( "
   252  			sql += b.dialect.Quote(strings.Join(pkList, b.dialect.Quote(",")))
   253  			sql += " ), "
   254  		}
   255  
   256  		sql = sql[:len(sql)-2]
   257  	}
   258  	sql += ")"
   259  
   260  	if b.dialect.SupportEngine() && storeEngine != "" {
   261  		sql += " ENGINE=" + storeEngine
   262  	}
   263  	if b.dialect.SupportCharset() {
   264  		if len(charset) == 0 {
   265  			charset = b.dialect.URI().Charset
   266  		}
   267  		if len(charset) > 0 {
   268  			sql += " DEFAULT CHARSET " + charset
   269  		}
   270  	}
   271  
   272  	return sql
   273  }
   274  
   275  func (b *Base) ForUpdateSql(query string) string {
   276  	return query + " FOR UPDATE"
   277  }
   278  
   279  func (b *Base) LogSQL(sql string, args []interface{}) {
   280  	if b.logger != nil && b.logger.IsShowSQL() {
   281  		if len(args) > 0 {
   282  			b.logger.Info("[sql]", sql, args)
   283  		} else {
   284  			b.logger.Info("[sql]", sql)
   285  		}
   286  	}
   287  }
   288  
   289  var (
   290  	dialects = map[DbType]func() Dialect{}
   291  )
   292  
   293  func RegisterDialect(dbName DbType, dialectFunc func() Dialect) {
   294  	if dialectFunc == nil {
   295  		panic("core: Register dialect is nil")
   296  	}
   297  	dialects[dbName] = dialectFunc // !nashtsai! allow override dialect
   298  }
   299  
   300  func QueryDialect(dbName DbType) Dialect {
   301  	return dialects[dbName]()
   302  }