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