stufflog graphql server
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

112 lines
2.4 KiB

  1. package mysqldriver
  2. import (
  3. "context"
  4. "database/sql"
  5. "git.aiterp.net/stufflog/server/database/repositories"
  6. "github.com/jmoiron/sqlx"
  7. "github.com/pressly/goose"
  8. "strings"
  9. // Mysql Driver
  10. _ "github.com/go-sql-driver/mysql"
  11. )
  12. type DB struct {
  13. db *sqlx.DB
  14. issues *issueRepository
  15. items *itemRepository
  16. projects *projectRepository
  17. sessions *sessionRepository
  18. users *userRepository
  19. projectStatuses *projectStatusRepository
  20. }
  21. func (db *DB) Issues() repositories.IssueRepository {
  22. return db.issues
  23. }
  24. func (db *DB) Items() repositories.ItemRepository {
  25. return db.items
  26. }
  27. func (db *DB) Projects() repositories.ProjectRepository {
  28. return db.projects
  29. }
  30. func (db *DB) Session() repositories.SessionRepository {
  31. return db.sessions
  32. }
  33. func (db *DB) Users() repositories.UserRepository {
  34. return db.users
  35. }
  36. func (db *DB) ProjectStatuses() repositories.ProjectStatusRepository {
  37. return db.projectStatuses
  38. }
  39. func (db *DB) Migrate() error {
  40. err := goose.SetDialect("mysql")
  41. if err != nil {
  42. return err
  43. }
  44. return goose.Up(db.db.DB, "migrations/mysql")
  45. }
  46. func Open(connectionString string) (*DB, error) {
  47. // Ensure parseTime is true
  48. qpos := strings.LastIndexByte(connectionString, '?')
  49. if qpos != -1 {
  50. connectionString += "&parseTime=true"
  51. } else {
  52. connectionString += "?parseTime=true"
  53. }
  54. // Connect to the database
  55. db, err := sqlx.Connect("mysql", connectionString)
  56. if err != nil {
  57. return nil, err
  58. }
  59. // Test the connection
  60. err = db.Ping()
  61. if err != nil {
  62. return nil, err
  63. }
  64. issues := &issueRepository{db: db}
  65. items := &itemRepository{db: db}
  66. projects := &projectRepository{db: db}
  67. users := &userRepository{db: db}
  68. sessions := &sessionRepository{db: db}
  69. projectStatuses := &projectStatusRepository{db: db}
  70. return &DB{
  71. db: db,
  72. issues: issues,
  73. items: items,
  74. projects: projects,
  75. users: users,
  76. sessions: sessions,
  77. projectStatuses: projectStatuses,
  78. }, nil
  79. }
  80. func incCounter(ctx context.Context, tx *sqlx.Tx, kind, name string) (int, error) {
  81. value := 1
  82. err := tx.GetContext(ctx, &value, `
  83. SELECT value FROM counters WHERE kind=? AND name=? FOR UPDATE
  84. `, kind, name)
  85. if err != nil && err != sql.ErrNoRows {
  86. return -1, err
  87. }
  88. _, err = tx.ExecContext(ctx, "REPLACE INTO counters (kind, name, value) VALUES (?, ?, ?)", kind, name, value+1)
  89. if err != nil {
  90. return -1, err
  91. }
  92. return value, nil
  93. }