queries.go 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. package models
  2. import (
  3. "context"
  4. "database/sql"
  5. "fmt"
  6. "github.com/jmoiron/sqlx"
  7. "github.com/lib/pq"
  8. )
  9. // Queries contains all prepared SQL queries.
  10. type Queries struct {
  11. GetDashboardCharts *sqlx.Stmt `query:"get-dashboard-charts"`
  12. GetDashboardCounts *sqlx.Stmt `query:"get-dashboard-counts"`
  13. InsertSubscriber *sqlx.Stmt `query:"insert-subscriber"`
  14. UpsertSubscriber *sqlx.Stmt `query:"upsert-subscriber"`
  15. UpsertBlocklistSubscriber *sqlx.Stmt `query:"upsert-blocklist-subscriber"`
  16. GetSubscriber *sqlx.Stmt `query:"get-subscriber"`
  17. GetSubscribersByEmails *sqlx.Stmt `query:"get-subscribers-by-emails"`
  18. GetSubscriberLists *sqlx.Stmt `query:"get-subscriber-lists"`
  19. GetSubscriptions *sqlx.Stmt `query:"get-subscriptions"`
  20. GetSubscriberListsLazy *sqlx.Stmt `query:"get-subscriber-lists-lazy"`
  21. UpdateSubscriber *sqlx.Stmt `query:"update-subscriber"`
  22. UpdateSubscriberWithLists *sqlx.Stmt `query:"update-subscriber-with-lists"`
  23. BlocklistSubscribers *sqlx.Stmt `query:"blocklist-subscribers"`
  24. AddSubscribersToLists *sqlx.Stmt `query:"add-subscribers-to-lists"`
  25. DeleteSubscriptions *sqlx.Stmt `query:"delete-subscriptions"`
  26. DeleteUnconfirmedSubscriptions *sqlx.Stmt `query:"delete-unconfirmed-subscriptions"`
  27. ConfirmSubscriptionOptin *sqlx.Stmt `query:"confirm-subscription-optin"`
  28. UnsubscribeSubscribersFromLists *sqlx.Stmt `query:"unsubscribe-subscribers-from-lists"`
  29. DeleteSubscribers *sqlx.Stmt `query:"delete-subscribers"`
  30. DeleteBlocklistedSubscribers *sqlx.Stmt `query:"delete-blocklisted-subscribers"`
  31. DeleteOrphanSubscribers *sqlx.Stmt `query:"delete-orphan-subscribers"`
  32. UnsubscribeByCampaign *sqlx.Stmt `query:"unsubscribe-by-campaign"`
  33. ExportSubscriberData *sqlx.Stmt `query:"export-subscriber-data"`
  34. // Non-prepared arbitrary subscriber queries.
  35. QuerySubscribers string `query:"query-subscribers"`
  36. QuerySubscribersCount string `query:"query-subscribers-count"`
  37. QuerySubscribersForExport string `query:"query-subscribers-for-export"`
  38. QuerySubscribersTpl string `query:"query-subscribers-template"`
  39. DeleteSubscribersByQuery string `query:"delete-subscribers-by-query"`
  40. AddSubscribersToListsByQuery string `query:"add-subscribers-to-lists-by-query"`
  41. BlocklistSubscribersByQuery string `query:"blocklist-subscribers-by-query"`
  42. DeleteSubscriptionsByQuery string `query:"delete-subscriptions-by-query"`
  43. UnsubscribeSubscribersFromListsByQuery string `query:"unsubscribe-subscribers-from-lists-by-query"`
  44. CreateList *sqlx.Stmt `query:"create-list"`
  45. QueryLists string `query:"query-lists"`
  46. GetLists *sqlx.Stmt `query:"get-lists"`
  47. GetListsByOptin *sqlx.Stmt `query:"get-lists-by-optin"`
  48. UpdateList *sqlx.Stmt `query:"update-list"`
  49. UpdateListsDate *sqlx.Stmt `query:"update-lists-date"`
  50. DeleteLists *sqlx.Stmt `query:"delete-lists"`
  51. CreateCampaign *sqlx.Stmt `query:"create-campaign"`
  52. QueryCampaigns string `query:"query-campaigns"`
  53. GetCampaign *sqlx.Stmt `query:"get-campaign"`
  54. GetCampaignForPreview *sqlx.Stmt `query:"get-campaign-for-preview"`
  55. GetCampaignStats *sqlx.Stmt `query:"get-campaign-stats"`
  56. GetCampaignStatus *sqlx.Stmt `query:"get-campaign-status"`
  57. GetArchivedCampaigns *sqlx.Stmt `query:"get-archived-campaigns"`
  58. // These two queries are read as strings and based on settings.individual_tracking=on/off,
  59. // are interpolated and copied to view and click counts. Same query, different tables.
  60. GetCampaignAnalyticsCounts string `query:"get-campaign-analytics-counts"`
  61. GetCampaignAnalyticsCountsUnique string `query:"get-campaign-analytics-unique-counts"`
  62. GetCampaignViewCounts *sqlx.Stmt `query:"get-campaign-view-counts"`
  63. GetCampaignClickCounts *sqlx.Stmt `query:"get-campaign-click-counts"`
  64. GetCampaignLinkCounts *sqlx.Stmt `query:"get-campaign-link-counts"`
  65. GetCampaignBounceCounts *sqlx.Stmt `query:"get-campaign-bounce-counts"`
  66. DeleteCampaignViews *sqlx.Stmt `query:"delete-campaign-views"`
  67. DeleteCampaignLinkClicks *sqlx.Stmt `query:"delete-campaign-link-clicks"`
  68. NextCampaigns *sqlx.Stmt `query:"next-campaigns"`
  69. NextCampaignSubscribers *sqlx.Stmt `query:"next-campaign-subscribers"`
  70. GetOneCampaignSubscriber *sqlx.Stmt `query:"get-one-campaign-subscriber"`
  71. UpdateCampaign *sqlx.Stmt `query:"update-campaign"`
  72. UpdateCampaignStatus *sqlx.Stmt `query:"update-campaign-status"`
  73. UpdateCampaignCounts *sqlx.Stmt `query:"update-campaign-counts"`
  74. UpdateCampaignArchive *sqlx.Stmt `query:"update-campaign-archive"`
  75. RegisterCampaignView *sqlx.Stmt `query:"register-campaign-view"`
  76. DeleteCampaign *sqlx.Stmt `query:"delete-campaign"`
  77. InsertMedia *sqlx.Stmt `query:"insert-media"`
  78. GetMedia *sqlx.Stmt `query:"get-media"`
  79. QueryMedia *sqlx.Stmt `query:"query-media"`
  80. DeleteMedia *sqlx.Stmt `query:"delete-media"`
  81. CreateTemplate *sqlx.Stmt `query:"create-template"`
  82. GetTemplates *sqlx.Stmt `query:"get-templates"`
  83. UpdateTemplate *sqlx.Stmt `query:"update-template"`
  84. SetDefaultTemplate *sqlx.Stmt `query:"set-default-template"`
  85. DeleteTemplate *sqlx.Stmt `query:"delete-template"`
  86. CreateLink *sqlx.Stmt `query:"create-link"`
  87. RegisterLinkClick *sqlx.Stmt `query:"register-link-click"`
  88. GetSettings *sqlx.Stmt `query:"get-settings"`
  89. UpdateSettings *sqlx.Stmt `query:"update-settings"`
  90. // GetStats *sqlx.Stmt `query:"get-stats"`
  91. RecordBounce *sqlx.Stmt `query:"record-bounce"`
  92. QueryBounces string `query:"query-bounces"`
  93. DeleteBounces *sqlx.Stmt `query:"delete-bounces"`
  94. DeleteBouncesBySubscriber *sqlx.Stmt `query:"delete-bounces-by-subscriber"`
  95. GetDBInfo string `query:"get-db-info"`
  96. }
  97. // CompileSubscriberQueryTpl takes an arbitrary WHERE expressions
  98. // to filter subscribers from the subscribers table and prepares a query
  99. // out of it using the raw `query-subscribers-template` query template.
  100. // While doing this, a readonly transaction is created and the query is
  101. // dry run on it to ensure that it is indeed readonly.
  102. func (q *Queries) CompileSubscriberQueryTpl(exp string, db *sqlx.DB) (string, error) {
  103. tx, err := db.BeginTxx(context.Background(), &sql.TxOptions{ReadOnly: true})
  104. if err != nil {
  105. return "", err
  106. }
  107. defer tx.Rollback()
  108. // Perform the dry run.
  109. if exp != "" {
  110. exp = " AND " + exp
  111. }
  112. stmt := fmt.Sprintf(q.QuerySubscribersTpl, exp)
  113. if _, err := tx.Exec(stmt, true, pq.Int64Array{}); err != nil {
  114. return "", err
  115. }
  116. return stmt, nil
  117. }
  118. // compileSubscriberQueryTpl takes an arbitrary WHERE expressions and a subscriber
  119. // query template that depends on the filter (eg: delete by query, blocklist by query etc.)
  120. // combines and executes them.
  121. func (q *Queries) ExecSubQueryTpl(exp, tpl string, listIDs []int, db *sqlx.DB, args ...interface{}) error {
  122. // Perform a dry run.
  123. filterExp, err := q.CompileSubscriberQueryTpl(exp, db)
  124. if err != nil {
  125. return err
  126. }
  127. if len(listIDs) == 0 {
  128. listIDs = []int{}
  129. }
  130. // First argument is the boolean indicating if the query is a dry run.
  131. a := append([]interface{}{false, pq.Array(listIDs)}, args...)
  132. if _, err := db.Exec(fmt.Sprintf(tpl, filterExp), a...); err != nil {
  133. return err
  134. }
  135. return nil
  136. }