dialect.go 6.3 KB

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