Refactor campaigns query into two: 'query' and 'get'
This commit is contained in:
parent
baa618475b
commit
93c952082c
5 changed files with 39 additions and 14 deletions
20
campaigns.go
20
campaigns.go
|
@ -21,8 +21,12 @@ import (
|
||||||
// campaignReq is a wrapper over the Campaign model.
|
// campaignReq is a wrapper over the Campaign model.
|
||||||
type campaignReq struct {
|
type campaignReq struct {
|
||||||
models.Campaign
|
models.Campaign
|
||||||
MessengerID string `json:"messenger"`
|
|
||||||
Lists pq.Int64Array `json:"lists"`
|
// This overrides Campaign.Lists to receive and
|
||||||
|
// write a list of int IDs during creation and updation.
|
||||||
|
// Campaign.Lists is JSONText for sending lists children
|
||||||
|
// to the outside world.
|
||||||
|
ListIDs pq.Int64Array `db:"-" json:"lists"`
|
||||||
|
|
||||||
// This is only relevant to campaign test requests.
|
// This is only relevant to campaign test requests.
|
||||||
SubscriberEmails pq.StringArray `json:"subscribers"`
|
SubscriberEmails pq.StringArray `json:"subscribers"`
|
||||||
|
@ -74,7 +78,7 @@ func handleGetCampaigns(c echo.Context) error {
|
||||||
query = string(regexFullTextQuery.ReplaceAll([]byte(query), []byte("&")))
|
query = string(regexFullTextQuery.ReplaceAll([]byte(query), []byte("&")))
|
||||||
}
|
}
|
||||||
|
|
||||||
err := app.Queries.GetCampaigns.Select(&out.Results, id, pq.StringArray(status), query, pg.Offset, pg.Limit)
|
err := app.Queries.QueryCampaigns.Select(&out.Results, id, pq.StringArray(status), query, pg.Offset, pg.Limit)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError,
|
return echo.NewHTTPError(http.StatusInternalServerError,
|
||||||
fmt.Sprintf("Error fetching campaigns: %s", pqErrMsg(err)))
|
fmt.Sprintf("Error fetching campaigns: %s", pqErrMsg(err)))
|
||||||
|
@ -199,7 +203,7 @@ func handleCreateCampaign(c echo.Context) error {
|
||||||
pq.StringArray(normalizeTags(o.Tags)),
|
pq.StringArray(normalizeTags(o.Tags)),
|
||||||
"email",
|
"email",
|
||||||
o.TemplateID,
|
o.TemplateID,
|
||||||
o.Lists,
|
o.ListIDs,
|
||||||
); err != nil {
|
); err != nil {
|
||||||
if err == sql.ErrNoRows {
|
if err == sql.ErrNoRows {
|
||||||
return echo.NewHTTPError(http.StatusBadRequest,
|
return echo.NewHTTPError(http.StatusBadRequest,
|
||||||
|
@ -230,7 +234,7 @@ func handleUpdateCampaign(c echo.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
var cm models.Campaign
|
var cm models.Campaign
|
||||||
if err := app.Queries.GetCampaigns.Get(&cm, id, "", 0, 1); err != nil {
|
if err := app.Queries.GetCampaign.Get(&cm, id); err != nil {
|
||||||
if err == sql.ErrNoRows {
|
if err == sql.ErrNoRows {
|
||||||
return echo.NewHTTPError(http.StatusBadRequest, "Campaign not found.")
|
return echo.NewHTTPError(http.StatusBadRequest, "Campaign not found.")
|
||||||
}
|
}
|
||||||
|
@ -263,7 +267,7 @@ func handleUpdateCampaign(c echo.Context) error {
|
||||||
o.SendAt,
|
o.SendAt,
|
||||||
pq.StringArray(normalizeTags(o.Tags)),
|
pq.StringArray(normalizeTags(o.Tags)),
|
||||||
o.TemplateID,
|
o.TemplateID,
|
||||||
o.Lists)
|
o.ListIDs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError,
|
return echo.NewHTTPError(http.StatusInternalServerError,
|
||||||
fmt.Sprintf("Error updating campaign: %s", pqErrMsg(err)))
|
fmt.Sprintf("Error updating campaign: %s", pqErrMsg(err)))
|
||||||
|
@ -288,7 +292,7 @@ func handleUpdateCampaignStatus(c echo.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
var cm models.Campaign
|
var cm models.Campaign
|
||||||
if err := app.Queries.GetCampaigns.Get(&cm, id, "", 0, 1); err != nil {
|
if err := app.Queries.GetCampaign.Get(&cm, id); err != nil {
|
||||||
if err == sql.ErrNoRows {
|
if err == sql.ErrNoRows {
|
||||||
return echo.NewHTTPError(http.StatusBadRequest, "Campaign not found.")
|
return echo.NewHTTPError(http.StatusBadRequest, "Campaign not found.")
|
||||||
}
|
}
|
||||||
|
@ -361,7 +365,7 @@ func handleDeleteCampaign(c echo.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
var cm models.Campaign
|
var cm models.Campaign
|
||||||
if err := app.Queries.GetCampaigns.Get(&cm, id, "", 0, 1); err != nil {
|
if err := app.Queries.GetCampaign.Get(&cm, id); err != nil {
|
||||||
if err == sql.ErrNoRows {
|
if err == sql.ErrNoRows {
|
||||||
return echo.NewHTTPError(http.StatusBadRequest, "Campaign not found.")
|
return echo.NewHTTPError(http.StatusBadRequest, "Campaign not found.")
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,7 @@ func (r *runnerDB) NextSubscribers(campID, limit int) ([]*models.Subscriber, err
|
||||||
// GetCampaign fetches a campaign from the database.
|
// GetCampaign fetches a campaign from the database.
|
||||||
func (r *runnerDB) GetCampaign(campID int) (*models.Campaign, error) {
|
func (r *runnerDB) GetCampaign(campID int) (*models.Campaign, error) {
|
||||||
var out = &models.Campaign{}
|
var out = &models.Campaign{}
|
||||||
err := r.queries.GetCampaigns.Get(out, campID, "", 0, 1)
|
err := r.queries.GetCampaign.Get(out, campID)
|
||||||
return out, err
|
return out, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -134,7 +134,7 @@ type Campaign struct {
|
||||||
Tags pq.StringArray `db:"tags" json:"tags"`
|
Tags pq.StringArray `db:"tags" json:"tags"`
|
||||||
TemplateID int `db:"template_id" json:"template_id"`
|
TemplateID int `db:"template_id" json:"template_id"`
|
||||||
MessengerID string `db:"messenger" json:"messenger"`
|
MessengerID string `db:"messenger" json:"messenger"`
|
||||||
Lists types.JSONText `json:"lists"`
|
Lists types.JSONText `db:"lists" json:"lists"`
|
||||||
|
|
||||||
View int `db:"views" json:"views"`
|
View int `db:"views" json:"views"`
|
||||||
Clicks int `db:"clicks" json:"clicks"`
|
Clicks int `db:"clicks" json:"clicks"`
|
||||||
|
|
|
@ -42,7 +42,8 @@ type Queries struct {
|
||||||
DeleteLists *sqlx.Stmt `query:"delete-lists"`
|
DeleteLists *sqlx.Stmt `query:"delete-lists"`
|
||||||
|
|
||||||
CreateCampaign *sqlx.Stmt `query:"create-campaign"`
|
CreateCampaign *sqlx.Stmt `query:"create-campaign"`
|
||||||
GetCampaigns *sqlx.Stmt `query:"get-campaigns"`
|
QueryCampaigns *sqlx.Stmt `query:"query-campaigns"`
|
||||||
|
GetCampaign *sqlx.Stmt `query:"get-campaign"`
|
||||||
GetCampaignForPreview *sqlx.Stmt `query:"get-campaign-for-preview"`
|
GetCampaignForPreview *sqlx.Stmt `query:"get-campaign-for-preview"`
|
||||||
GetCampaignStats *sqlx.Stmt `query:"get-campaign-stats"`
|
GetCampaignStats *sqlx.Stmt `query:"get-campaign-stats"`
|
||||||
NextCampaigns *sqlx.Stmt `query:"next-campaigns"`
|
NextCampaigns *sqlx.Stmt `query:"next-campaigns"`
|
||||||
|
|
26
queries.sql
26
queries.sql
|
@ -252,7 +252,7 @@ INSERT INTO campaign_lists (campaign_id, list_id, list_name)
|
||||||
(SELECT (SELECT id FROM camp), id, name FROM lists WHERE id=ANY($11::INT[]))
|
(SELECT (SELECT id FROM camp), id, name FROM lists WHERE id=ANY($11::INT[]))
|
||||||
RETURNING (SELECT id FROM camp);
|
RETURNING (SELECT id FROM camp);
|
||||||
|
|
||||||
-- name: get-campaigns
|
-- name: query-campaigns
|
||||||
-- Here, 'lists' is returned as an aggregated JSON array from campaign_lists because
|
-- Here, 'lists' is returned as an aggregated JSON array from campaign_lists because
|
||||||
-- the list reference may have been deleted.
|
-- the list reference may have been deleted.
|
||||||
-- While the results are sliced using offset+limit,
|
-- While the results are sliced using offset+limit,
|
||||||
|
@ -290,6 +290,26 @@ LEFT JOIN views AS v ON (v.campaign_id = camps.id)
|
||||||
LEFT JOIN clicks AS c ON (c.campaign_id = camps.id)
|
LEFT JOIN clicks AS c ON (c.campaign_id = camps.id)
|
||||||
ORDER BY camps.created_at DESC;
|
ORDER BY camps.created_at DESC;
|
||||||
|
|
||||||
|
-- name: get-campaign
|
||||||
|
WITH camp AS (
|
||||||
|
SELECT * FROM campaigns WHERE id = $1
|
||||||
|
), views AS (
|
||||||
|
SELECT campaign_id, COUNT(campaign_id) as num FROM campaign_views
|
||||||
|
WHERE campaign_id = ANY(SELECT id FROM camp)
|
||||||
|
GROUP BY campaign_id
|
||||||
|
),
|
||||||
|
clicks AS (
|
||||||
|
SELECT campaign_id, COUNT(campaign_id) as num FROM link_clicks
|
||||||
|
WHERE campaign_id = ANY(SELECT id FROM camp)
|
||||||
|
GROUP BY campaign_id
|
||||||
|
)
|
||||||
|
SELECT *,
|
||||||
|
COALESCE(v.num, 0) AS views,
|
||||||
|
COALESCE(c.num, 0) AS clicks
|
||||||
|
FROM camp
|
||||||
|
LEFT JOIN views AS v ON (v.campaign_id = camp.id)
|
||||||
|
LEFT JOIN clicks AS c ON (c.campaign_id = camp.id);
|
||||||
|
|
||||||
-- name: get-campaign-for-preview
|
-- name: get-campaign-for-preview
|
||||||
SELECT campaigns.*, COALESCE(templates.body, (SELECT body FROM templates WHERE is_default = true LIMIT 1)) AS template_body,
|
SELECT campaigns.*, COALESCE(templates.body, (SELECT body FROM templates WHERE is_default = true LIMIT 1)) AS template_body,
|
||||||
(
|
(
|
||||||
|
@ -394,9 +414,9 @@ WITH camp AS (
|
||||||
updated_at=NOW()
|
updated_at=NOW()
|
||||||
WHERE id = $1 RETURNING id
|
WHERE id = $1 RETURNING id
|
||||||
),
|
),
|
||||||
-- Reset the relationships
|
|
||||||
d AS (
|
d AS (
|
||||||
DELETE FROM campaign_lists WHERE campaign_id = $1
|
-- Reset list relationships
|
||||||
|
DELETE FROM campaign_lists WHERE campaign_id = $1 AND NOT(list_id = ANY($10))
|
||||||
)
|
)
|
||||||
INSERT INTO campaign_lists (campaign_id, list_id, list_name)
|
INSERT INTO campaign_lists (campaign_id, list_id, list_name)
|
||||||
(SELECT $1 as campaign_id, id, name FROM lists WHERE id=ANY($10::INT[]))
|
(SELECT $1 as campaign_id, id, name FROM lists WHERE id=ANY($10::INT[]))
|
||||||
|
|
Loading…
Reference in a new issue