dialect.go 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  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. type Base struct {
  71. db *DB
  72. dialect Dialect
  73. driverName string
  74. dataSourceName string
  75. logger ILogger
  76. *Uri
  77. }
  78. func (b *Base) DB() *DB {
  79. return b.db
  80. }
  81. func (b *Base) SetLogger(logger ILogger) {
  82. b.logger = logger
  83. }
  84. func (b *Base) Init(db *DB, dialect Dialect, uri *Uri, drivername, dataSourceName string) error {
  85. b.db, b.dialect, b.Uri = db, dialect, uri
  86. b.driverName, b.dataSourceName = drivername, dataSourceName
  87. return nil
  88. }
  89. func (b *Base) URI() *Uri {
  90. return b.Uri
  91. }
  92. func (b *Base) DBType() DbType {
  93. return b.Uri.DbType
  94. }
  95. func (b *Base) FormatBytes(bs []byte) string {
  96. return fmt.Sprintf("0x%x", bs)
  97. }
  98. func (b *Base) DriverName() string {
  99. return b.driverName
  100. }
  101. func (b *Base) ShowCreateNull() bool {
  102. return true
  103. }
  104. func (b *Base) DataSourceName() string {
  105. return b.dataSourceName
  106. }
  107. func (b *Base) AndStr() string {
  108. return "AND"
  109. }
  110. func (b *Base) OrStr() string {
  111. return "OR"
  112. }
  113. func (b *Base) EqStr() string {
  114. return "="
  115. }
  116. func (db *Base) RollBackStr() string {
  117. return "ROLL BACK"
  118. }
  119. func (db *Base) SupportDropIfExists() bool {
  120. return true
  121. }
  122. func (db *Base) DropTableSql(tableName string) string {
  123. quote := db.dialect.Quote
  124. return fmt.Sprintf("DROP TABLE IF EXISTS %s", quote(tableName))
  125. }
  126. func (db *Base) HasRecords(query string, args ...interface{}) (bool, error) {
  127. db.LogSQL(query, args)
  128. rows, err := db.DB().Query(query, args...)
  129. if err != nil {
  130. return false, err
  131. }
  132. defer rows.Close()
  133. if rows.Next() {
  134. return true, nil
  135. }
  136. return false, nil
  137. }
  138. func (db *Base) IsColumnExist(tableName, colName string) (bool, error) {
  139. query := "SELECT `COLUMN_NAME` FROM `INFORMATION_SCHEMA`.`COLUMNS` WHERE `TABLE_SCHEMA` = ? AND `TABLE_NAME` = ? AND `COLUMN_NAME` = ?"
  140. query = strings.Replace(query, "`", db.dialect.QuoteStr(), -1)
  141. return db.HasRecords(query, db.DbName, tableName, colName)
  142. }
  143. /*
  144. func (db *Base) CreateTableIfNotExists(table *Table, tableName, storeEngine, charset string) error {
  145. sql, args := db.dialect.TableCheckSql(tableName)
  146. rows, err := db.DB().Query(sql, args...)
  147. if db.Logger != nil {
  148. db.Logger.Info("[sql]", sql, args)
  149. }
  150. if err != nil {
  151. return err
  152. }
  153. defer rows.Close()
  154. if rows.Next() {
  155. return nil
  156. }
  157. sql = db.dialect.CreateTableSql(table, tableName, storeEngine, charset)
  158. _, err = db.DB().Exec(sql)
  159. if db.Logger != nil {
  160. db.Logger.Info("[sql]", sql)
  161. }
  162. return err
  163. }*/
  164. func (db *Base) CreateIndexSql(tableName string, index *Index) string {
  165. quote := db.dialect.Quote
  166. var unique string
  167. var idxName string
  168. if index.Type == UniqueType {
  169. unique = " UNIQUE"
  170. }
  171. idxName = index.XName(tableName)
  172. return fmt.Sprintf("CREATE%s INDEX %v ON %v (%v)", unique,
  173. quote(idxName), quote(tableName),
  174. quote(strings.Join(index.Cols, quote(","))))
  175. }
  176. func (db *Base) DropIndexSql(tableName string, index *Index) string {
  177. quote := db.dialect.Quote
  178. var name string
  179. if index.IsRegular {
  180. name = index.XName(tableName)
  181. } else {
  182. name = index.Name
  183. }
  184. return fmt.Sprintf("DROP INDEX %v ON %s", quote(name), quote(tableName))
  185. }
  186. func (db *Base) ModifyColumnSql(tableName string, col *Column) string {
  187. return fmt.Sprintf("alter table %s MODIFY COLUMN %s", tableName, col.StringNoPk(db.dialect))
  188. }
  189. func (b *Base) CreateTableSql(table *Table, tableName, storeEngine, charset string) string {
  190. var sql string
  191. sql = "CREATE TABLE IF NOT EXISTS "
  192. if tableName == "" {
  193. tableName = table.Name
  194. }
  195. sql += b.dialect.Quote(tableName)
  196. sql += " ("
  197. if len(table.ColumnsSeq()) > 0 {
  198. pkList := table.PrimaryKeys
  199. for _, colName := range table.ColumnsSeq() {
  200. col := table.GetColumn(colName)
  201. if col.IsPrimaryKey && len(pkList) == 1 {
  202. sql += col.String(b.dialect)
  203. } else {
  204. sql += col.StringNoPk(b.dialect)
  205. }
  206. sql = strings.TrimSpace(sql)
  207. if b.DriverName() == MYSQL && len(col.Comment) > 0 {
  208. sql += " COMMENT '" + col.Comment + "'"
  209. }
  210. sql += ", "
  211. }
  212. if len(pkList) > 1 {
  213. sql += "PRIMARY KEY ( "
  214. sql += b.dialect.Quote(strings.Join(pkList, b.dialect.Quote(",")))
  215. sql += " ), "
  216. }
  217. sql = sql[:len(sql)-2]
  218. }
  219. sql += ")"
  220. if b.dialect.SupportEngine() && storeEngine != "" {
  221. sql += " ENGINE=" + storeEngine
  222. }
  223. if b.dialect.SupportCharset() {
  224. if len(charset) == 0 {
  225. charset = b.dialect.URI().Charset
  226. }
  227. if len(charset) > 0 {
  228. sql += " DEFAULT CHARSET " + charset
  229. }
  230. }
  231. return sql
  232. }
  233. func (b *Base) ForUpdateSql(query string) string {
  234. return query + " FOR UPDATE"
  235. }
  236. func (b *Base) LogSQL(sql string, args []interface{}) {
  237. if b.logger != nil && b.logger.IsShowSQL() {
  238. if len(args) > 0 {
  239. b.logger.Infof("[SQL] %v %v", sql, args)
  240. } else {
  241. b.logger.Infof("[SQL] %v", sql)
  242. }
  243. }
  244. }
  245. func (b *Base) SetParams(params map[string]string) {
  246. }
  247. var (
  248. dialects = map[string]func() Dialect{}
  249. )
  250. // RegisterDialect register database dialect
  251. func RegisterDialect(dbName DbType, dialectFunc func() Dialect) {
  252. if dialectFunc == nil {
  253. panic("core: Register dialect is nil")
  254. }
  255. dialects[strings.ToLower(string(dbName))] = dialectFunc // !nashtsai! allow override dialect
  256. }
  257. // QueryDialect query if registed database dialect
  258. func QueryDialect(dbName DbType) Dialect {
  259. if d, ok := dialects[strings.ToLower(string(dbName))]; ok {
  260. return d()
  261. }
  262. return nil
  263. }