sqlite.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. package sqlite
  2. import (
  3. "database/sql"
  4. "strconv"
  5. "strings"
  6. _ "github.com/mattn/go-sqlite3"
  7. "gorm.io/gorm"
  8. "gorm.io/gorm/callbacks"
  9. "gorm.io/gorm/clause"
  10. "gorm.io/gorm/logger"
  11. "gorm.io/gorm/migrator"
  12. "gorm.io/gorm/schema"
  13. )
  14. // DriverName is the default driver name for SQLite.
  15. const DriverName = "sqlite3"
  16. type Dialector struct {
  17. DriverName string
  18. DSN string
  19. Conn gorm.ConnPool
  20. }
  21. func Open(dsn string) gorm.Dialector {
  22. return &Dialector{DSN: dsn}
  23. }
  24. func (dialector Dialector) Name() string {
  25. return "sqlite"
  26. }
  27. func (dialector Dialector) Initialize(db *gorm.DB) (err error) {
  28. if dialector.DriverName == "" {
  29. dialector.DriverName = DriverName
  30. }
  31. // register callbacks
  32. callbacks.RegisterDefaultCallbacks(db, &callbacks.Config{
  33. LastInsertIDReversed: true,
  34. })
  35. if dialector.Conn != nil {
  36. db.ConnPool = dialector.Conn
  37. } else {
  38. db.ConnPool, err = sql.Open(dialector.DriverName, dialector.DSN)
  39. if err != nil {
  40. return err
  41. }
  42. }
  43. for k, v := range dialector.ClauseBuilders() {
  44. db.ClauseBuilders[k] = v
  45. }
  46. return
  47. }
  48. func (dialector Dialector) ClauseBuilders() map[string]clause.ClauseBuilder {
  49. return map[string]clause.ClauseBuilder{
  50. "INSERT": func(c clause.Clause, builder clause.Builder) {
  51. if insert, ok := c.Expression.(clause.Insert); ok {
  52. if stmt, ok := builder.(*gorm.Statement); ok {
  53. stmt.WriteString("INSERT ")
  54. if insert.Modifier != "" {
  55. stmt.WriteString(insert.Modifier)
  56. stmt.WriteByte(' ')
  57. }
  58. stmt.WriteString("INTO ")
  59. if insert.Table.Name == "" {
  60. stmt.WriteQuoted(stmt.Table)
  61. } else {
  62. stmt.WriteQuoted(insert.Table)
  63. }
  64. return
  65. }
  66. }
  67. c.Build(builder)
  68. },
  69. "LIMIT": func(c clause.Clause, builder clause.Builder) {
  70. if limit, ok := c.Expression.(clause.Limit); ok {
  71. if limit.Limit > 0 {
  72. builder.WriteString("LIMIT ")
  73. builder.WriteString(strconv.Itoa(limit.Limit))
  74. }
  75. if limit.Offset > 0 {
  76. if limit.Limit > 0 {
  77. builder.WriteString(" ")
  78. }
  79. builder.WriteString("OFFSET ")
  80. builder.WriteString(strconv.Itoa(limit.Offset))
  81. }
  82. }
  83. },
  84. "FOR": func(c clause.Clause, builder clause.Builder) {
  85. if _, ok := c.Expression.(clause.Locking); ok {
  86. // SQLite3 does not support row-level locking.
  87. return
  88. }
  89. c.Build(builder)
  90. },
  91. }
  92. }
  93. func (dialector Dialector) DefaultValueOf(field *schema.Field) clause.Expression {
  94. if field.AutoIncrement {
  95. return clause.Expr{SQL: "NULL"}
  96. }
  97. // doesn't work, will raise error
  98. return clause.Expr{SQL: "DEFAULT"}
  99. }
  100. func (dialector Dialector) Migrator(db *gorm.DB) gorm.Migrator {
  101. return Migrator{migrator.Migrator{Config: migrator.Config{
  102. DB: db,
  103. Dialector: dialector,
  104. CreateIndexAfterCreateTable: true,
  105. }}}
  106. }
  107. func (dialector Dialector) BindVarTo(writer clause.Writer, stmt *gorm.Statement, v interface{}) {
  108. writer.WriteByte('?')
  109. }
  110. func (dialector Dialector) QuoteTo(writer clause.Writer, str string) {
  111. writer.WriteByte('`')
  112. if strings.Contains(str, ".") {
  113. for idx, str := range strings.Split(str, ".") {
  114. if idx > 0 {
  115. writer.WriteString(".`")
  116. }
  117. writer.WriteString(str)
  118. writer.WriteByte('`')
  119. }
  120. } else {
  121. writer.WriteString(str)
  122. writer.WriteByte('`')
  123. }
  124. }
  125. func (dialector Dialector) Explain(sql string, vars ...interface{}) string {
  126. return logger.ExplainSQL(sql, nil, `"`, vars...)
  127. }
  128. func (dialector Dialector) DataTypeOf(field *schema.Field) string {
  129. switch field.DataType {
  130. case schema.Bool:
  131. return "numeric"
  132. case schema.Int, schema.Uint:
  133. if field.AutoIncrement && !field.PrimaryKey {
  134. // https://www.sqlite.org/autoinc.html
  135. return "integer PRIMARY KEY AUTOINCREMENT"
  136. } else {
  137. return "integer"
  138. }
  139. case schema.Float:
  140. return "real"
  141. case schema.String:
  142. return "text"
  143. case schema.Time:
  144. return "datetime"
  145. case schema.Bytes:
  146. return "blob"
  147. }
  148. return string(field.DataType)
  149. }
  150. func (dialectopr Dialector) SavePoint(tx *gorm.DB, name string) error {
  151. tx.Exec("SAVEPOINT " + name)
  152. return nil
  153. }
  154. func (dialectopr Dialector) RollbackTo(tx *gorm.DB, name string) error {
  155. tx.Exec("ROLLBACK TO SAVEPOINT " + name)
  156. return nil
  157. }