dialect.go 7.1 KB

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