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
|
|
|
|
}
|
|
|
|
|
|
|
|
// a dialect is a driver's wrapper
|
|
|
|
type Dialect interface {
|
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-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
|
|
|
|
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
|
|
|
//ColumnCheckSql(tableName, colName string) (string, []interface{})
|
|
|
|
|
|
|
|
//IsTableExist(tableName string) (bool, error)
|
|
|
|
//IsIndexExist(tableName string, idx *Index) (bool, error)
|
|
|
|
IsColumnExist(tableName string, col *Column) (bool, error)
|
|
|
|
|
2014-04-17 02:13:51 +00:00
|
|
|
CreateTableSql(table *Table, tableName, storeEngine, charset string) string
|
2014-04-23 07:23:03 +00:00
|
|
|
DropTableSql(tableName string) string
|
2014-04-17 02:13:51 +00:00
|
|
|
CreateIndexSql(tableName string, index *Index) string
|
2014-06-11 06:02:22 +00:00
|
|
|
DropIndexSql(tableName string, index *Index) string
|
|
|
|
|
|
|
|
ModifyColumnSql(tableName string, col *Column) string
|
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
|
|
|
// Get data from db cell to a struct's field
|
|
|
|
//GetData(col *Column, fieldValue *reflect.Value, cellData interface{}) error
|
|
|
|
// Set field data to db
|
|
|
|
//SetData(col *Column, fieldValue *refelct.Value) (interface{}, error)
|
2014-04-08 12:57:04 +00:00
|
|
|
|
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
|
|
|
|
*Uri
|
|
|
|
}
|
|
|
|
|
2014-04-18 10:39:59 +00:00
|
|
|
func (b *Base) DB() *DB {
|
|
|
|
return b.db
|
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
|
|
|
func (b *Base) Quote(c string) string {
|
|
|
|
return b.dialect.QuoteStr() + c + b.dialect.QuoteStr()
|
|
|
|
}
|
|
|
|
|
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) DropTableSql(tableName string) string {
|
|
|
|
return fmt.Sprintf("DROP TABLE IF EXISTS `%s`", tableName)
|
|
|
|
}
|
|
|
|
|
2014-05-09 04:51:11 +00:00
|
|
|
func (db *Base) HasRecords(query string, args ...interface{}) (bool, error) {
|
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
|
|
|
}
|
|
|
|
|
2014-05-09 04:51:11 +00:00
|
|
|
func (db *Base) IsColumnExist(tableName string, col *Column) (bool, error) {
|
|
|
|
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)
|
|
|
|
return db.HasRecords(query, db.DbName, tableName, col.Name)
|
|
|
|
}
|
|
|
|
|
2014-04-17 02:13:51 +00:00
|
|
|
func (db *Base) CreateIndexSql(tableName string, index *Index) string {
|
|
|
|
quote := db.Quote
|
|
|
|
var unique string
|
|
|
|
var idxName string
|
|
|
|
if index.Type == UniqueType {
|
|
|
|
unique = " UNIQUE"
|
|
|
|
idxName = fmt.Sprintf("UQE_%v_%v", tableName, index.Name)
|
|
|
|
} else {
|
|
|
|
idxName = fmt.Sprintf("IDX_%v_%v", tableName, index.Name)
|
|
|
|
}
|
|
|
|
return fmt.Sprintf("CREATE%s INDEX %v ON %v (%v);", unique,
|
|
|
|
quote(idxName), quote(tableName),
|
|
|
|
quote(strings.Join(index.Cols, quote(","))))
|
|
|
|
}
|
|
|
|
|
2014-06-11 06:02:22 +00:00
|
|
|
func (db *Base) DropIndexSql(tableName string, index *Index) string {
|
|
|
|
quote := db.Quote
|
|
|
|
//var unique string
|
|
|
|
var idxName string = index.Name
|
|
|
|
if !strings.HasPrefix(idxName, "UQE_") &&
|
|
|
|
!strings.HasPrefix(idxName, "IDX_") {
|
|
|
|
if index.Type == UniqueType {
|
|
|
|
idxName = fmt.Sprintf("UQE_%v_%v", tableName, index.Name)
|
|
|
|
} else {
|
|
|
|
idxName = fmt.Sprintf("IDX_%v_%v", tableName, index.Name)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return fmt.Sprintf("DROP INDEX %v ON %s",
|
|
|
|
quote(idxName), 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.Quote(tableName) + " ("
|
|
|
|
|
|
|
|
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)
|
|
|
|
sql += ", "
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(pkList) > 1 {
|
|
|
|
sql += "PRIMARY KEY ( "
|
|
|
|
sql += b.Quote(strings.Join(pkList, b.Quote(",")))
|
|
|
|
sql += " ), "
|
|
|
|
}
|
|
|
|
|
|
|
|
sql = sql[:len(sql)-2] + ")"
|
|
|
|
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
|
|
|
}
|
|
|
|
sql += ";"
|
|
|
|
return sql
|
|
|
|
}
|
|
|
|
|
|
|
|
var (
|
2014-04-11 13:05:08 +00:00
|
|
|
dialects = map[DbType]Dialect{}
|
2014-04-08 12:57:04 +00:00
|
|
|
)
|
|
|
|
|
2014-04-11 13:05:08 +00:00
|
|
|
func RegisterDialect(dbName DbType, dialect Dialect) {
|
2014-04-08 12:57:04 +00:00
|
|
|
if dialect == nil {
|
|
|
|
panic("core: Register dialect is nil")
|
|
|
|
}
|
2014-04-11 13:05:08 +00:00
|
|
|
dialects[dbName] = dialect // !nashtsai! allow override dialect
|
2014-04-08 12:57:04 +00:00
|
|
|
}
|
|
|
|
|
2014-04-11 13:05:08 +00:00
|
|
|
func QueryDialect(dbName DbType) Dialect {
|
2014-04-08 12:57:04 +00:00
|
|
|
return dialects[dbName]
|
|
|
|
}
|