dialect.go 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  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. Schema string
  21. }
  22. // a dialect is a driver's wrapper
  23. type Dialect interface {
  24. SetLogger(logger ILogger)
  25. Init(*DB, *Uri, string, string) error
  26. URI() *Uri
  27. DB() *DB
  28. DBType() DbType
  29. SqlType(*Column) string
  30. FormatBytes(b []byte) string
  31. DriverName() string
  32. DataSourceName() string
  33. QuoteStr() string
  34. IsReserved(string) bool
  35. Quote(string) string
  36. AndStr() string
  37. OrStr() string
  38. EqStr() string
  39. RollBackStr() string
  40. AutoIncrStr() string
  41. SupportInsertMany() bool
  42. SupportEngine() bool
  43. SupportCharset() bool
  44. SupportDropIfExists() bool
  45. IndexOnTable() bool
  46. ShowCreateNull() bool
  47. IndexCheckSql(tableName, idxName string) (string, []interface{})
  48. TableCheckSql(tableName string) (string, []interface{})
  49. IsColumnExist(tableName string, colName string) (bool, error)
  50. CreateTableSql(table *Table, tableName, storeEngine, charset string) string
  51. DropTableSql(tableName string) string
  52. CreateIndexSql(tableName string, index *Index) string
  53. DropIndexSql(tableName string, index *Index) string
  54. ModifyColumnSql(tableName string, col *Column) string
  55. ForUpdateSql(query string) string
  56. //CreateTableIfNotExists(table *Table, tableName, storeEngine, charset string) error
  57. //MustDropTable(tableName string) error
  58. GetColumns(tableName string) ([]string, map[string]*Column, error)
  59. GetTables() ([]*Table, error)
  60. GetIndexes(tableName string) (map[string]*Index, error)
  61. Filters() []Filter
  62. SetParams(params map[string]string)
  63. }
  64. func OpenDialect(dialect Dialect) (*DB, error) {
  65. return Open(dialect.DriverName(), dialect.DataSourceName())
  66. }
  67. type Base struct {
  68. db *DB
  69. dialect Dialect
  70. driverName string
  71. dataSourceName string
  72. logger ILogger
  73. *Uri
  74. }
  75. func (b *Base) DB() *DB {
  76. return b.db
  77. }
  78. func (b *Base) SetLogger(logger ILogger) {
  79. b.logger = logger
  80. }
  81. func (b *Base) Init(db *DB, dialect Dialect, uri *Uri, drivername, dataSourceName string) error {
  82. b.db, b.dialect, b.Uri = db, dialect, uri
  83. b.driverName, b.dataSourceName = drivername, dataSourceName
  84. return nil
  85. }
  86. func (b *Base) URI() *Uri {
  87. return b.Uri
  88. }
  89. func (b *Base) DBType() DbType {
  90. return b.Uri.DbType
  91. }
  92. func (b *Base) FormatBytes(bs []byte) string {
  93. return fmt.Sprintf("0x%x", bs)
  94. }
  95. func (b *Base) DriverName() string {
  96. return b.driverName
  97. }
  98. func (b *Base) ShowCreateNull() bool {
  99. return true
  100. }
  101. func (b *Base) DataSourceName() string {
  102. return b.dataSourceName
  103. }
  104. func (b *Base) AndStr() string {
  105. return "AND"
  106. }
  107. func (b *Base) OrStr() string {
  108. return "OR"
  109. }
  110. func (b *Base) EqStr() string {
  111. return "="
  112. }
  113. func (db *Base) RollBackStr() string {
  114. return "ROLL BACK"
  115. }
  116. func (db *Base) SupportDropIfExists() bool {
  117. return true
  118. }
  119. func (db *Base) DropTableSql(tableName string) string {
  120. return fmt.Sprintf("DROP TABLE IF EXISTS `%s`", tableName)
  121. }
  122. func (db *Base) HasRecords(query string, args ...interface{}) (bool, error) {
  123. db.LogSQL(query, args)
  124. rows, err := db.DB().Query(query, args...)
  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. if b.DriverName() == MYSQL && len(col.Comment) > 0 {
  204. sql += " COMMENT '" + col.Comment + "'"
  205. }
  206. sql += ", "
  207. }
  208. if len(pkList) > 1 {
  209. sql += "PRIMARY KEY ( "
  210. sql += b.dialect.Quote(strings.Join(pkList, b.dialect.Quote(",")))
  211. sql += " ), "
  212. }
  213. sql = sql[:len(sql)-2]
  214. }
  215. sql += ")"
  216. if b.dialect.SupportEngine() && storeEngine != "" {
  217. sql += " ENGINE=" + storeEngine
  218. }
  219. if b.dialect.SupportCharset() {
  220. if len(charset) == 0 {
  221. charset = b.dialect.URI().Charset
  222. }
  223. if len(charset) > 0 {
  224. sql += " DEFAULT CHARSET " + charset
  225. }
  226. }
  227. return sql
  228. }
  229. func (b *Base) ForUpdateSql(query string) string {
  230. return query + " FOR UPDATE"
  231. }
  232. func (b *Base) LogSQL(sql string, args []interface{}) {
  233. if b.logger != nil && b.logger.IsShowSQL() {
  234. if len(args) > 0 {
  235. b.logger.Infof("[SQL] %v %v", sql, args)
  236. } else {
  237. b.logger.Infof("[SQL] %v", sql)
  238. }
  239. }
  240. }
  241. func (b *Base) SetParams(params map[string]string) {
  242. }
  243. var (
  244. dialects = map[string]func() Dialect{}
  245. )
  246. // RegisterDialect register database dialect
  247. func RegisterDialect(dbName DbType, dialectFunc func() Dialect) {
  248. if dialectFunc == nil {
  249. panic("core: Register dialect is nil")
  250. }
  251. dialects[strings.ToLower(string(dbName))] = dialectFunc // !nashtsai! allow override dialect
  252. }
  253. // QueryDialect query if registed database dialect
  254. func QueryDialect(dbName DbType) Dialect {
  255. if d, ok := dialects[strings.ToLower(string(dbName))]; ok {
  256. return d()
  257. }
  258. return nil
  259. }