xorm/dialect.go

311 lines
6.8 KiB
Go
Raw Normal View History

2014-04-08 12:57:04 +00:00
package core
import (
2014-04-11 07:38:09 +00:00
"fmt"
2014-04-08 12:57:04 +00:00
"strings"
"time"
)
2014-04-11 13:05:08 +00:00
type DbType string
2014-04-08 12:57:04 +00:00
type Uri struct {
2014-04-11 13:05:08 +00:00
DbType DbType
2014-04-08 12:57:04 +00:00
Proto string
Host string
Port string
DbName string
User string
Passwd string
Charset string
Laddr string
Raddr string
Timeout time.Duration
2016-03-03 03:01:50 +00:00
Schema string
2014-04-08 12:57:04 +00:00
}
// a dialect is a driver's wrapper
type Dialect interface {
2014-11-08 10:51:42 +00:00
SetLogger(logger ILogger)
2014-04-18 10:39:59 +00:00
Init(*DB, *Uri, string, string) error
2014-04-08 12:57:04 +00:00
URI() *Uri
2014-04-18 10:39:59 +00:00
DB() *DB
2014-04-11 13:05:08 +00:00
DBType() DbType
2014-04-17 02:13:51 +00:00
SqlType(*Column) string
2014-05-04 05:52:56 +00:00
FormatBytes(b []byte) string
2014-04-17 02:13:51 +00:00
2014-04-23 07:23:03 +00:00
DriverName() string
DataSourceName() string
2014-04-08 12:57:04 +00:00
QuoteStr() string
2014-09-06 15:26:23 +00:00
IsReserved(string) bool
Quote(string) string
2014-04-13 07:37:25 +00:00
AndStr() string
2014-04-17 02:13:51 +00:00
OrStr() string
2014-04-13 07:37:25 +00:00
EqStr() string
2014-04-11 07:38:09 +00:00
RollBackStr() string
2014-04-08 12:57:04 +00:00
AutoIncrStr() string
2014-04-17 02:13:51 +00:00
SupportInsertMany() bool
2014-04-08 12:57:04 +00:00
SupportEngine() bool
SupportCharset() bool
SupportDropIfExists() bool
2014-04-08 12:57:04 +00:00
IndexOnTable() bool
2014-04-13 07:37:25 +00:00
ShowCreateNull() bool
2014-04-08 12:57:04 +00:00
IndexCheckSql(tableName, idxName string) (string, []interface{})
TableCheckSql(tableName string) (string, []interface{})
2014-04-23 07:23:03 +00:00
2015-05-19 14:38:07 +00:00
IsColumnExist(tableName string, colName string) (bool, error)
2014-04-23 07:23:03 +00:00
2014-04-17 02:13:51 +00:00
CreateTableSql(table *Table, tableName, storeEngine, charset string) string
2015-03-12 10:04:32 +00:00
DropTableSql(tableName string) string
2014-04-17 02:13:51 +00:00
CreateIndexSql(tableName string, index *Index) string
DropIndexSql(tableName string, index *Index) string
ModifyColumnSql(tableName string, col *Column) string
2014-04-08 12:57:04 +00:00
ForUpdateSql(query string) string
2015-03-12 10:04:32 +00:00
//CreateTableIfNotExists(table *Table, tableName, storeEngine, charset string) error
//MustDropTable(tableName string) error
2015-03-12 10:04:32 +00:00
2014-04-08 12:57:04 +00:00
GetColumns(tableName string) ([]string, map[string]*Column, error)
GetTables() ([]*Table, error)
GetIndexes(tableName string) (map[string]*Index, error)
2014-04-23 07:23:03 +00:00
Filters() []Filter
2014-04-08 12:57:04 +00:00
}
2014-04-15 02:45:38 +00:00
func OpenDialect(dialect Dialect) (*DB, error) {
return Open(dialect.DriverName(), dialect.DataSourceName())
}
2014-04-08 12:57:04 +00:00
type Base struct {
2014-04-18 10:39:59 +00:00
db *DB
2014-04-08 12:57:04 +00:00
dialect Dialect
driverName string
dataSourceName string
2016-02-16 09:14:10 +00:00
logger ILogger
2014-04-08 12:57:04 +00:00
*Uri
}
2014-04-18 10:39:59 +00:00
func (b *Base) DB() *DB {
return b.db
}
2014-11-08 10:51:42 +00:00
func (b *Base) SetLogger(logger ILogger) {
2016-02-16 09:14:10 +00:00
b.logger = logger
2014-11-08 10:51:42 +00:00
}
2014-04-18 10:39:59 +00:00
func (b *Base) Init(db *DB, dialect Dialect, uri *Uri, drivername, dataSourceName string) error {
b.db, b.dialect, b.Uri = db, dialect, uri
2014-04-08 12:57:04 +00:00
b.driverName, b.dataSourceName = drivername, dataSourceName
return nil
}
func (b *Base) URI() *Uri {
return b.Uri
}
2014-04-11 13:05:08 +00:00
func (b *Base) DBType() DbType {
2014-04-08 12:57:04 +00:00
return b.Uri.DbType
}
2014-05-04 05:52:56 +00:00
func (b *Base) FormatBytes(bs []byte) string {
return fmt.Sprintf("0x%x", bs)
}
2014-04-08 12:57:04 +00:00
func (b *Base) DriverName() string {
return b.driverName
}
2014-04-13 07:37:25 +00:00
func (b *Base) ShowCreateNull() bool {
return true
}
2014-04-08 12:57:04 +00:00
func (b *Base) DataSourceName() string {
return b.dataSourceName
}
2014-04-13 07:37:25 +00:00
func (b *Base) AndStr() string {
return "AND"
}
2014-04-17 02:13:51 +00:00
func (b *Base) OrStr() string {
return "OR"
}
2014-04-13 07:37:25 +00:00
func (b *Base) EqStr() string {
return "="
}
2014-04-11 07:38:09 +00:00
func (db *Base) RollBackStr() string {
return "ROLL BACK"
}
func (db *Base) SupportDropIfExists() bool {
return true
2014-04-11 07:38:09 +00:00
}
func (db *Base) DropTableSql(tableName string) string {
return fmt.Sprintf("DROP TABLE IF EXISTS `%s`", tableName)
2015-03-03 07:06:48 +00:00
}
2014-05-09 04:51:11 +00:00
func (db *Base) HasRecords(query string, args ...interface{}) (bool, error) {
2016-02-16 09:14:10 +00:00
db.LogSQL(query, args)
2014-04-23 07:23:03 +00:00
rows, err := db.DB().Query(query, args...)
if err != nil {
return false, err
}
defer rows.Close()
if rows.Next() {
return true, nil
}
2014-05-09 01:43:35 +00:00
return false, nil
2014-04-23 07:23:03 +00:00
}
2015-05-19 14:38:07 +00:00
func (db *Base) IsColumnExist(tableName, colName string) (bool, error) {
2014-05-09 04:51:11 +00:00
query := "SELECT `COLUMN_NAME` FROM `INFORMATION_SCHEMA`.`COLUMNS` WHERE `TABLE_SCHEMA` = ? AND `TABLE_NAME` = ? AND `COLUMN_NAME` = ?"
query = strings.Replace(query, "`", db.dialect.QuoteStr(), -1)
2015-05-19 14:38:07 +00:00
return db.HasRecords(query, db.DbName, tableName, colName)
2014-05-09 04:51:11 +00:00
}
2015-03-12 10:04:32 +00:00
/*
func (db *Base) CreateTableIfNotExists(table *Table, tableName, storeEngine, charset string) error {
sql, args := db.dialect.TableCheckSql(tableName)
rows, err := db.DB().Query(sql, args...)
if db.Logger != nil {
db.Logger.Info("[sql]", sql, args)
}
if err != nil {
return err
}
defer rows.Close()
if rows.Next() {
return nil
}
sql = db.dialect.CreateTableSql(table, tableName, storeEngine, charset)
_, err = db.DB().Exec(sql)
if db.Logger != nil {
db.Logger.Info("[sql]", sql)
}
return err
}*/
2014-04-17 02:13:51 +00:00
func (db *Base) CreateIndexSql(tableName string, index *Index) string {
2014-09-06 15:26:23 +00:00
quote := db.dialect.Quote
2014-04-17 02:13:51 +00:00
var unique string
var idxName string
if index.Type == UniqueType {
unique = " UNIQUE"
}
2015-02-17 07:00:51 +00:00
idxName = index.XName(tableName)
2015-03-12 10:04:32 +00:00
return fmt.Sprintf("CREATE%s INDEX %v ON %v (%v)", unique,
2014-04-17 02:13:51 +00:00
quote(idxName), quote(tableName),
quote(strings.Join(index.Cols, quote(","))))
}
func (db *Base) DropIndexSql(tableName string, index *Index) string {
2014-09-06 15:26:23 +00:00
quote := db.dialect.Quote
2015-02-17 07:00:51 +00:00
var name string
if index.IsRegular {
name = index.XName(tableName)
} else {
name = index.Name
}
2015-02-17 07:00:51 +00:00
return fmt.Sprintf("DROP INDEX %v ON %s", quote(name), quote(tableName))
}
func (db *Base) ModifyColumnSql(tableName string, col *Column) string {
return fmt.Sprintf("alter table %s MODIFY COLUMN %s", tableName, col.StringNoPk(db.dialect))
}
2014-04-08 12:57:04 +00:00
func (b *Base) CreateTableSql(table *Table, tableName, storeEngine, charset string) string {
var sql string
sql = "CREATE TABLE IF NOT EXISTS "
if tableName == "" {
tableName = table.Name
}
sql += b.dialect.Quote(tableName)
sql += " ("
if len(table.ColumnsSeq()) > 0 {
pkList := table.PrimaryKeys
for _, colName := range table.ColumnsSeq() {
col := table.GetColumn(colName)
if col.IsPrimaryKey && len(pkList) == 1 {
sql += col.String(b.dialect)
} else {
sql += col.StringNoPk(b.dialect)
}
sql = strings.TrimSpace(sql)
2017-06-14 06:05:17 +00:00
if b.DriverName() == MYSQL && len(col.Comment) > 0 {
sql += " COMMENT '" + col.Comment + "'"
}
sql += ", "
}
2014-04-08 12:57:04 +00:00
if len(pkList) > 1 {
sql += "PRIMARY KEY ( "
sql += b.dialect.Quote(strings.Join(pkList, b.dialect.Quote(",")))
sql += " ), "
2014-04-08 12:57:04 +00:00
}
sql = sql[:len(sql)-2]
2014-04-08 12:57:04 +00:00
}
sql += ")"
2014-04-08 12:57:04 +00:00
if b.dialect.SupportEngine() && storeEngine != "" {
sql += " ENGINE=" + storeEngine
}
if b.dialect.SupportCharset() {
2014-04-17 12:55:06 +00:00
if len(charset) == 0 {
2014-04-08 12:57:04 +00:00
charset = b.dialect.URI().Charset
}
2014-04-17 12:55:06 +00:00
if len(charset) > 0 {
sql += " DEFAULT CHARSET " + charset
}
2014-04-08 12:57:04 +00:00
}
2014-04-08 12:57:04 +00:00
return sql
}
func (b *Base) ForUpdateSql(query string) string {
return query + " FOR UPDATE"
}
2016-02-16 09:14:10 +00:00
func (b *Base) LogSQL(sql string, args []interface{}) {
if b.logger != nil && b.logger.IsShowSQL() {
if len(args) > 0 {
2017-03-17 12:25:07 +00:00
b.logger.Infof("[SQL] %v %v", sql, args)
2016-02-16 09:14:10 +00:00
} else {
2017-03-17 12:25:07 +00:00
b.logger.Infof("[SQL] %v", sql)
2016-02-16 09:14:10 +00:00
}
}
}
2014-04-08 12:57:04 +00:00
var (
2017-01-03 06:45:57 +00:00
dialects = map[string]func() Dialect{}
2014-04-08 12:57:04 +00:00
)
// RegisterDialect register database dialect
2015-06-26 13:20:29 +00:00
func RegisterDialect(dbName DbType, dialectFunc func() Dialect) {
if dialectFunc == nil {
2014-04-08 12:57:04 +00:00
panic("core: Register dialect is nil")
}
2017-01-03 06:45:57 +00:00
dialects[strings.ToLower(string(dbName))] = dialectFunc // !nashtsai! allow override dialect
2014-04-08 12:57:04 +00:00
}
// QueryDialect query if registed database dialect
2014-04-11 13:05:08 +00:00
func QueryDialect(dbName DbType) Dialect {
2017-01-03 06:45:57 +00:00
if d, ok := dialects[strings.ToLower(string(dbName))]; ok {
return d()
}
return nil
2014-04-08 12:57:04 +00:00
}