tag.go 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. package store
  2. import (
  3. "context"
  4. "database/sql"
  5. "fmt"
  6. "strings"
  7. )
  8. type Tag struct {
  9. Name string
  10. CreatorID int
  11. }
  12. type FindTag struct {
  13. CreatorID int
  14. }
  15. type DeleteTag struct {
  16. Name string
  17. CreatorID int
  18. }
  19. func (s *Store) UpsertTag(ctx context.Context, upsert *Tag) (*Tag, error) {
  20. tx, err := s.db.BeginTx(ctx, nil)
  21. if err != nil {
  22. return nil, err
  23. }
  24. defer tx.Rollback()
  25. query := `
  26. INSERT INTO tag (
  27. name, creator_id
  28. )
  29. VALUES (?, ?)
  30. ON CONFLICT(name, creator_id) DO UPDATE
  31. SET
  32. name = EXCLUDED.name
  33. `
  34. if _, err := tx.ExecContext(ctx, query, upsert.Name, upsert.CreatorID); err != nil {
  35. return nil, err
  36. }
  37. if err := tx.Commit(); err != nil {
  38. return nil, err
  39. }
  40. tag := upsert
  41. return tag, nil
  42. }
  43. func (s *Store) ListTags(ctx context.Context, find *FindTag) ([]*Tag, error) {
  44. tx, err := s.db.BeginTx(ctx, nil)
  45. if err != nil {
  46. return nil, err
  47. }
  48. defer tx.Rollback()
  49. where, args := []string{"creator_id = ?"}, []any{find.CreatorID}
  50. query := `
  51. SELECT
  52. name,
  53. creator_id
  54. FROM tag
  55. WHERE ` + strings.Join(where, " AND ") + `
  56. ORDER BY name ASC
  57. `
  58. rows, err := tx.QueryContext(ctx, query, args...)
  59. if err != nil {
  60. return nil, err
  61. }
  62. defer rows.Close()
  63. list := []*Tag{}
  64. for rows.Next() {
  65. tag := &Tag{}
  66. if err := rows.Scan(
  67. &tag.Name,
  68. &tag.CreatorID,
  69. ); err != nil {
  70. return nil, err
  71. }
  72. list = append(list, tag)
  73. }
  74. if err := rows.Err(); err != nil {
  75. return nil, err
  76. }
  77. if err := tx.Commit(); err != nil {
  78. return nil, err
  79. }
  80. return list, nil
  81. }
  82. func (s *Store) DeleteTag(ctx context.Context, delete *DeleteTag) error {
  83. tx, err := s.db.BeginTx(ctx, nil)
  84. if err != nil {
  85. return err
  86. }
  87. defer tx.Rollback()
  88. where, args := []string{"name = ?", "creator_id = ?"}, []any{delete.Name, delete.CreatorID}
  89. query := `DELETE FROM tag WHERE ` + strings.Join(where, " AND ")
  90. result, err := tx.ExecContext(ctx, query, args...)
  91. if err != nil {
  92. return err
  93. }
  94. rows, _ := result.RowsAffected()
  95. if rows == 0 {
  96. return fmt.Errorf("tag not found")
  97. }
  98. if err := tx.Commit(); err != nil {
  99. // Prevent linter warning.
  100. return err
  101. }
  102. return nil
  103. }
  104. func vacuumTag(ctx context.Context, tx *sql.Tx) error {
  105. stmt := `
  106. DELETE FROM
  107. tag
  108. WHERE
  109. creator_id NOT IN (
  110. SELECT
  111. id
  112. FROM
  113. user
  114. )`
  115. _, err := tx.ExecContext(ctx, stmt)
  116. if err != nil {
  117. return err
  118. }
  119. return nil
  120. }