/db/db.go

https://github.com/bakape/hydron · Go · 83 lines · 71 code · 7 blank · 5 comment · 16 complexity · 1d51e61f356e8b59fad5f6d066c19553 MD5 · raw file

  1. package db
  2. import (
  3. "database/sql"
  4. "encoding/json"
  5. "fmt"
  6. "io/ioutil"
  7. "os"
  8. "path/filepath"
  9. "strings"
  10. "github.com/Masterminds/squirrel"
  11. "github.com/bakape/hydron/files"
  12. _ "github.com/lib/pq"
  13. _ "github.com/mattn/go-sqlite3"
  14. )
  15. var (
  16. db *sql.DB
  17. sq squirrel.StatementBuilderType
  18. driver string
  19. )
  20. func Open() (err error) {
  21. // Read config file, if any
  22. var conf struct {
  23. Driver, Connection string
  24. }
  25. buf, err := ioutil.ReadFile(filepath.Join(files.RootPath, "db_conf.json"))
  26. switch {
  27. case os.IsNotExist(err):
  28. err = nil
  29. case err == nil:
  30. err = json.Unmarshal(buf, &conf)
  31. if err != nil {
  32. return
  33. }
  34. default:
  35. return
  36. }
  37. if conf.Driver == "" || conf.Connection == "" {
  38. conf.Driver = "sqlite3"
  39. // Shared cache is required for multithreading
  40. conf.Connection = fmt.Sprintf("file:%s?cache=shared&mode=rwc",
  41. filepath.Join(files.RootPath, "db.db"))
  42. }
  43. driver = conf.Driver
  44. db, err = sql.Open(conf.Driver, conf.Connection)
  45. if err != nil {
  46. return
  47. }
  48. sq = squirrel.StatementBuilder.RunWith(squirrel.NewStmtCacheProxy(db))
  49. switch conf.Driver {
  50. case "sqlite3":
  51. // To avoid locking "database locked" errors. Hard limitation of SQLite,
  52. // when used from multiple threads.
  53. db.SetMaxOpenConns(1)
  54. case "postgres":
  55. sq = sq.PlaceholderFormat(squirrel.Dollar)
  56. }
  57. var currentVersion int
  58. err = sq.Select("val").
  59. From("main").
  60. Where("id = 'version'").
  61. QueryRow().
  62. Scan(&currentVersion)
  63. if err != nil {
  64. if s := err.Error(); strings.HasPrefix(s, "no such table") ||
  65. s == `pq: relation "main" does not exist` {
  66. err = nil
  67. } else {
  68. return
  69. }
  70. }
  71. return runMigrations(currentVersion, version)
  72. }
  73. // Close database connection
  74. func Close() error {
  75. return db.Close()
  76. }