storage.go 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. /*
  2. The "storage" package in Kurz provides the data model.
  3. In its current implementation:
  4. - it is specific to MySQL/MariaDB and compatibles SQL engines.
  5. - data model and data access are not isolated
  6. - it assumes the DB has been initialized by importing the data/db-schema.sql file
  7. - it initializes the connection info based on the "dsn" CLI flag
  8. */
  9. package storage
  10. /**
  11. TODO use a CLI flag to clear the database on init
  12. TODO use a CLI flag to install the database schema
  13. */
  14. import (
  15. "database/sql"
  16. "flag"
  17. _ "github.com/go-sql-driver/mysql"
  18. "log"
  19. )
  20. type StorageInterface interface {
  21. Controller() StorageControllerInterface
  22. }
  23. type Storage struct {
  24. DB *sql.DB
  25. DSN string
  26. truncateList []string
  27. }
  28. var Service Storage = Storage{}
  29. /*
  30. Open() established the database connection, making sure it is actually available instead of just preparing the connection info.
  31. */
  32. func (s *Storage) Open() error {
  33. var err error
  34. s.DB, err = sql.Open("mysql", s.DSN)
  35. if err == nil {
  36. err = s.DB.Ping()
  37. }
  38. return err
  39. }
  40. /*
  41. Close() closes the database connection and releases its information.
  42. */
  43. func (s *Storage) Close() {
  44. if s.DB != nil {
  45. for _, name := range s.truncateList {
  46. s.Truncate(name)
  47. }
  48. s.DB.Close()
  49. }
  50. s.DB = nil
  51. }
  52. func (s *Storage) AddToTruncateList(name string) {
  53. s.truncateList = append(s.truncateList, name)
  54. }
  55. func (s *Storage) Truncate(name string) {
  56. if s.DB == nil {
  57. panic("Cannot truncate a non-connected database.")
  58. }
  59. // Cannot use truncate on a master table (longurl vs shorturl) with MySQL.
  60. _, err := s.DB.Exec("DELETE FROM " + name)
  61. if err != nil {
  62. log.Printf("Error truncating %s: %+v\n", name, err)
  63. }
  64. }
  65. /*
  66. SetDSN() sets the DSN information for the storage.
  67. */
  68. func (s *Storage) SetDSN(dsn string) {
  69. s.DSN = dsn
  70. }
  71. type StorageControllerInterface interface {
  72. Storage() StorageInterface
  73. Table() string
  74. }
  75. type StorageController struct {
  76. StorageInstance StorageInterface
  77. table string
  78. }
  79. func (sc StorageController) Storage() StorageInterface {
  80. return nil
  81. }
  82. func (sc StorageController) Table() string {
  83. return sc.table
  84. }
  85. /*
  86. init() initializes the storage information from the command-line flag "dsn".
  87. */
  88. func init() {
  89. var dsn = flag.String("dsn", "root:@tcp(localhost:3306)/go_kurz", "some_user:some_pass@tcp(some_host:some_port)/some_db")
  90. flag.Parse()
  91. Service.SetDSN(*dsn)
  92. }