Update started / upcoming logic for milestone filters

What does this MR do and why?

This change updates the logic for the milestones filters "started" and "upcoming", according to the changes outlined in this table. The summary of these changes are:

  • Upcoming
    • Use the start_date instead of the due_date to determine if a milestone is upcoming (and apply the reverse logic to the inverse scope)
    • Returns all upcoming milestones, not just the next for a given group / project
  • Started
    • Use an open-ended overlap check with the current date, and exclude milestones which do not have at least one of start_date and due_date, to avoid cluttering the view

These changes are behind the new_milestone_filtering_logic feature flag. Note that this flag will only apply the new filter logic for views within a single group / project. Cross-group queries, such as the dashboards page will continue to use the existing filtering logic regardless of the state of the flag, as the feature flag is scoped to a specific namespace. The feature flag rollout issue is available here.

References

Screenshots or screen recordings

Filter Before After

%Upcoming

Screenshot_2025-04-16_at_2.58.11_pm

Shows items in the current milestone (first milestone with due_date after current date)

Screenshot 2025-04-16 at 2.56.09 pm.png

Shows items in upcoming milestones (milestones with a start_date in the future)

%Started

Screenshot_2025-04-16_at_4.34.57_pm

Shows items whose milestone start date is on or before the current date. Does not include work items whose associated milestone does not have a start date

Screenshot_2025-04-16_at_4.34.23_pm

Shows items whose milestone start date is null or on or before today AND end date is null or in the future. Also excludes items with a milestone that doesn't have a defined start date / due date

How to set up and validate locally

Prerequisites

Started filter

  1. Create an issue and assign it to a milestone with a null start date, and a due date in the future
  2. Create an issue and assign it to a milestone with a start date in the past, and a null due date
  3. Create an issue and assign it to a milestone with a null start date and a null due date
  4. On the Group > Issues page, Project > Issues page, or an Issue board, filter for issues by Milestone is %Started
  5. Observe that only the issues with a start or due date are returned

Upcoming filter

  1. Create an issue and assign it to a milestone with a start date in the past
  2. Create an issue and assign it to a milestone with a start date in the future
  3. On the Group > Issues page, Project > Issues page, or an Issue board, filter for issues by Milestone is %Upcoming
  4. Observe that only the issue with a milestone starting in future is returned

Not upcoming filter

  1. Create an issue and assign it to a milestone with a start date in the past
  2. Create an issue and assign it to a milestone with a start date in the future
  3. On the Group > Issues page, Project > Issues page, or an Issue board, filter for issues by Milestone != %Upcoming
  4. Observe that only the issue with a milestone starting in the past is returned
  • Note that the logic for the != %Started filter has not changed

MR acceptance checklist

Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.

Database

Raw SQL before changes

Boards Query Raw SQL Before (With Upcoming Filter)

SELECT "issues"."id",
       "issues"."title",
       "issues"."author_id",
       "issues"."project_id",
       "issues"."created_at",
       "issues"."updated_at",
       "issues"."description",
       "issues"."milestone_id",
       "issues"."iid",
       "issues"."updated_by_id",
       "issues"."weight",
       "issues"."confidential",
       "issues"."moved_to_id",
       "issues"."due_date",
       "issues"."lock_version",
       "issues"."title_html",
       "issues"."description_html",
       "issues"."time_estimate",
       "issues"."relative_position",
       "issues"."service_desk_reply_to",
       "issues"."cached_markdown_version",
       "issues"."last_edited_at",
       "issues"."last_edited_by_id",
       "issues"."discussion_locked",
       "issues"."closed_at",
       "issues"."closed_by_id",
       "issues"."state_id",
       "issues"."duplicated_to_id",
       "issues"."promoted_to_epic_id",
       "issues"."health_status",
       "issues"."external_key",
       "issues"."sprint_id",
       "issues"."blocking_issues_count",
       "issues"."upvotes_count",
       "issues"."work_item_type_id",
       "issues"."namespace_id",
       "issues"."start_date",
       "issues"."imported_from"
FROM "issues"
         LEFT OUTER JOIN milestones ON issues.milestone_id = milestones.id
WHERE (NOT EXISTS (SELECT 1 FROM "banned_users" WHERE (issues.author_id = banned_users.user_id)))
  AND "issues"."project_id" = 278964
  AND "issues"."state_id" = 1
  AND "issues"."milestone_id" IN (SELECT DISTINCT ON (project_id, group_id) id
                                  FROM ((SELECT "milestones".*
                                         FROM "milestones"
                                         WHERE "milestones"."project_id" = 278964)
                                        UNION ALL
                                        (SELECT "milestones".*
                                         FROM "milestones"
                                         WHERE "milestones"."group_id" IN (SELECT "namespaces"."id"
                                                                           FROM "namespaces"
                                                                           WHERE "namespaces"."type" = 'Group'
                                                                             AND "namespaces"."id" = 9970))) milestones
                                  WHERE ("milestones"."state" IN ('active'))
                                    AND (milestones.due_date > CURRENT_DATE)
                                  ORDER BY "milestones"."project_id" ASC, "milestones"."group_id" ASC,
                                           "milestones"."due_date" ASC)
  AND "issues"."work_item_type_id" IN (1, 2, 5)
ORDER BY "issues"."relative_position" ASC NULLS LAST, "issues"."id" ASC
LIMIT 11
Boards Query Raw SQL Before (With Started Filter)

SELECT "issues"."id",
       "issues"."title",
       "issues"."author_id",
       "issues"."project_id",
       "issues"."created_at",
       "issues"."updated_at",
       "issues"."description",
       "issues"."milestone_id",
       "issues"."iid",
       "issues"."updated_by_id",
       "issues"."weight",
       "issues"."confidential",
       "issues"."moved_to_id",
       "issues"."due_date",
       "issues"."lock_version",
       "issues"."title_html",
       "issues"."description_html",
       "issues"."time_estimate",
       "issues"."relative_position",
       "issues"."service_desk_reply_to",
       "issues"."cached_markdown_version",
       "issues"."last_edited_at",
       "issues"."last_edited_by_id",
       "issues"."discussion_locked",
       "issues"."closed_at",
       "issues"."closed_by_id",
       "issues"."state_id",
       "issues"."duplicated_to_id",
       "issues"."promoted_to_epic_id",
       "issues"."health_status",
       "issues"."external_key",
       "issues"."sprint_id",
       "issues"."blocking_issues_count",
       "issues"."upvotes_count",
       "issues"."work_item_type_id",
       "issues"."namespace_id",
       "issues"."start_date",
       "issues"."imported_from"
FROM "issues"
         LEFT OUTER JOIN milestones ON issues.milestone_id = milestones.id
WHERE (NOT EXISTS (SELECT 1 FROM "banned_users" WHERE (issues.author_id = banned_users.user_id)))
  AND "issues"."project_id" = 278964
  AND "issues"."state_id" = 2
  AND ("milestones"."state" IN ('active'))
  AND (milestones.start_date <= CURRENT_DATE)
  AND "issues"."work_item_type_id" IN (1, 2, 5)
ORDER BY "issues"."closed_at" DESC NULLS LAST, "issues"."id" DESC
LIMIT 11

Group > Issues Query Raw SQL Before (With Upcoming Filter)


SELECT "issues"."id",
       "issues"."title",
       "issues"."author_id",
       "issues"."project_id",
       "issues"."created_at",
       "issues"."updated_at",
       "issues"."description",
       "issues"."milestone_id",
       "issues"."iid",
       "issues"."updated_by_id",
       "issues"."weight",
       "issues"."confidential",
       "issues"."moved_to_id",
       "issues"."due_date",
       "issues"."lock_version",
       "issues"."title_html",
       "issues"."description_html",
       "issues"."time_estimate",
       "issues"."relative_position",
       "issues"."service_desk_reply_to",
       "issues"."cached_markdown_version",
       "issues"."last_edited_at",
       "issues"."last_edited_by_id",
       "issues"."discussion_locked",
       "issues"."closed_at",
       "issues"."closed_by_id",
       "issues"."state_id",
       "issues"."duplicated_to_id",
       "issues"."promoted_to_epic_id",
       "issues"."health_status",
       "issues"."external_key",
       "issues"."sprint_id",
       "issues"."blocking_issues_count",
       "issues"."upvotes_count",
       "issues"."work_item_type_id",
       "issues"."namespace_id",
       "issues"."start_date",
       "issues"."imported_from"
FROM "issues"
         INNER JOIN "projects" ON "projects"."id" = "issues"."project_id"
         LEFT JOIN project_features ON projects.id = project_features.project_id
         LEFT OUTER JOIN milestones ON issues.milestone_id = milestones.id
WHERE (NOT EXISTS (SELECT 1 FROM "banned_users" WHERE (issues.author_id = banned_users.user_id)))
  AND "projects"."namespace_id" IN (SELECT "namespaces"."id"
                                    FROM UNNEST(COALESCE((SELECT ids
                                                          FROM (SELECT "namespace_descendants"."self_and_descendant_group_ids" AS ids
                                                                FROM "namespace_descendants"
                                                                WHERE "namespace_descendants"."outdated_at" IS NULL
                                                                  AND "namespace_descendants"."namespace_id" = 9970) cached_query),
                                                         (SELECT ids
                                                          FROM (SELECT ARRAY_AGG("namespaces"."id") AS ids
                                                                FROM (SELECT namespaces.traversal_ids[array_length(namespaces.traversal_ids, 1)] AS id
                                                                      FROM "namespaces"
                                                                      WHERE "namespaces"."type" = 'Group'
                                                                        AND (traversal_ids @> ('{9970}'))) namespaces) consistent_query))) AS namespaces(id))
  AND (EXISTS (SELECT 1
               FROM "project_authorizations"
               WHERE "project_authorizations"."user_id" = 25345642
                 AND (project_authorizations.project_id = projects.id)
                 AND (project_authorizations.access_level >= 10)) OR projects.visibility_level IN (10, 20))
  AND ("project_features"."issues_access_level" IS NULL OR "project_features"."issues_access_level" IN (20, 30) OR
       ("project_features"."issues_access_level" = 10 AND EXISTS (SELECT 1
                                                                  FROM "project_authorizations"
                                                                  WHERE "project_authorizations"."user_id" = 25345642
                                                                    AND (project_authorizations.project_id = project_features.project_id)
                                                                    AND (project_authorizations.access_level >= 10))))
  AND "issues"."state_id" = 1
  AND ("issues"."project_id" IS NULL OR "projects"."archived" = FALSE)
  AND "issues"."milestone_id" IN (SELECT DISTINCT ON (project_id, group_id) id
                                  FROM ((SELECT "milestones".*
                                         FROM "milestones"
                                         WHERE "milestones"."project_id" IN (SELECT "projects"."id"
                                                                             FROM "projects"
                                                                                      LEFT JOIN project_features ON projects.id = project_features.project_id
                                                                             WHERE "projects"."namespace_id" IN
                                                                                   (SELECT "namespaces"."id"
                                                                                    FROM UNNEST(COALESCE((SELECT ids
                                                                                                          FROM (SELECT "namespace_descendants"."self_and_descendant_group_ids" AS ids
                                                                                                                FROM "namespace_descendants"
                                                                                                                WHERE "namespace_descendants"."outdated_at" IS NULL
                                                                                                                  AND "namespace_descendants"."namespace_id" = 9970) cached_query),
                                                                                                         (SELECT ids
                                                                                                          FROM (SELECT ARRAY_AGG("namespaces"."id") AS ids
                                                                                                                FROM (SELECT namespaces.traversal_ids[array_length(namespaces.traversal_ids, 1)] AS id
                                                                                                                      FROM "namespaces"
                                                                                                                      WHERE "namespaces"."type" = 'Group'
                                                                                                                        AND (traversal_ids @> ('{9970}'))) namespaces) consistent_query))) AS namespaces(id))
                                                                               AND (EXISTS (SELECT 1
                                                                                            FROM "project_authorizations"
                                                                                            WHERE "project_authorizations"."user_id" = 25345642
                                                                                              AND (project_authorizations.project_id = projects.id)
                                                                                              AND (project_authorizations.access_level >= 10)) OR
                                                                                    projects.visibility_level IN (10,
                                                                                                                  20))
                                                                               AND (
                                                                                 "project_features"."issues_access_level" IS NULL OR
                                                                                 "project_features"."issues_access_level" IN
                                                                                 (20, 30) OR
                                                                                 ("project_features"."issues_access_level" =
                                                                                  10 AND EXISTS (SELECT 1
                                                                                                 FROM "project_authorizations"
                                                                                                 WHERE "project_authorizations"."user_id" = 25345642
                                                                                                   AND (project_authorizations.project_id = project_features.project_id)
                                                                                                   AND (project_authorizations.access_level >= 10))))))
                                        UNION ALL
                                        (SELECT "milestones".*
                                         FROM "milestones"
                                         WHERE "milestones"."group_id" = 9970)) milestones
                                  WHERE ("milestones"."state" IN ('active'))
                                    AND (milestones.due_date > CURRENT_DATE)
                                  ORDER BY "milestones"."project_id" ASC, "milestones"."group_id" ASC,
                                           "milestones"."due_date" ASC)
  AND "issues"."work_item_type_id" IN (1, 2, 5, 7, 6, 3)
ORDER BY "issues"."created_at" ASC, "issues"."id" DESC
LIMIT 21

Group > Issues Query Raw SQL Before (With Started Filter)


SELECT "issues"."id",
       "issues"."title",
       "issues"."author_id",
       "issues"."project_id",
       "issues"."created_at",
       "issues"."updated_at",
       "issues"."description",
       "issues"."milestone_id",
       "issues"."iid",
       "issues"."updated_by_id",
       "issues"."weight",
       "issues"."confidential",
       "issues"."moved_to_id",
       "issues"."due_date",
       "issues"."lock_version",
       "issues"."title_html",
       "issues"."description_html",
       "issues"."time_estimate",
       "issues"."relative_position",
       "issues"."service_desk_reply_to",
       "issues"."cached_markdown_version",
       "issues"."last_edited_at",
       "issues"."last_edited_by_id",
       "issues"."discussion_locked",
       "issues"."closed_at",
       "issues"."closed_by_id",
       "issues"."state_id",
       "issues"."duplicated_to_id",
       "issues"."promoted_to_epic_id",
       "issues"."health_status",
       "issues"."external_key",
       "issues"."sprint_id",
       "issues"."blocking_issues_count",
       "issues"."upvotes_count",
       "issues"."work_item_type_id",
       "issues"."namespace_id",
       "issues"."start_date",
       "issues"."imported_from"
FROM "issues"
         INNER JOIN "projects" ON "projects"."id" = "issues"."project_id"
         LEFT JOIN project_features ON projects.id = project_features.project_id
         LEFT OUTER JOIN milestones ON issues.milestone_id = milestones.id
WHERE (NOT EXISTS (SELECT 1 FROM "banned_users" WHERE (issues.author_id = banned_users.user_id)))
  AND "projects"."namespace_id" IN (SELECT "namespaces"."id"
                                    FROM UNNEST(COALESCE((SELECT ids
                                                          FROM (SELECT "namespace_descendants"."self_and_descendant_group_ids" AS ids
                                                                FROM "namespace_descendants"
                                                                WHERE "namespace_descendants"."outdated_at" IS NULL
                                                                  AND "namespace_descendants"."namespace_id" = 9970) cached_query),
                                                         (SELECT ids
                                                          FROM (SELECT ARRAY_AGG("namespaces"."id") AS ids
                                                                FROM (SELECT namespaces.traversal_ids[array_length(namespaces.traversal_ids, 1)] AS id
                                                                      FROM "namespaces"
                                                                      WHERE "namespaces"."type" = 'Group'
                                                                        AND (traversal_ids @> ('{9970}'))) namespaces) consistent_query))) AS namespaces(id))
  AND (EXISTS (SELECT 1
               FROM "project_authorizations"
               WHERE "project_authorizations"."user_id" = 25345642
                 AND (project_authorizations.project_id = projects.id)
                 AND (project_authorizations.access_level >= 10)) OR projects.visibility_level IN (10, 20))
  AND ("project_features"."issues_access_level" IS NULL OR "project_features"."issues_access_level" IN (20, 30) OR
       ("project_features"."issues_access_level" = 10 AND EXISTS (SELECT 1
                                                                  FROM "project_authorizations"
                                                                  WHERE "project_authorizations"."user_id" = 25345642
                                                                    AND (project_authorizations.project_id = project_features.project_id)
                                                                    AND (project_authorizations.access_level >= 10))))
  AND "issues"."state_id" = 1
  AND ("issues"."project_id" IS NULL OR "projects"."archived" = FALSE)
  AND ("milestones"."state" IN ('active'))
  AND (milestones.start_date <= CURRENT_DATE)
  AND "issues"."work_item_type_id" IN (1, 2, 5, 7, 6, 3)
ORDER BY "issues"."created_at" ASC, "issues"."id" DESC
LIMIT 21

Raw SQL after changes

Boards Query Raw SQL After (With Upcoming Filter)
SELECT "issues"."id",
       "issues"."title",
       "issues"."author_id",
       "issues"."project_id",
       "issues"."created_at",
       "issues"."updated_at",
       "issues"."description",
       "issues"."milestone_id",
       "issues"."iid",
       "issues"."updated_by_id",
       "issues"."weight",
       "issues"."confidential",
       "issues"."due_date",
       "issues"."moved_to_id",
       "issues"."lock_version",
       "issues"."title_html",
       "issues"."description_html",
       "issues"."time_estimate",
       "issues"."relative_position",
       "issues"."service_desk_reply_to",
       "issues"."cached_markdown_version",
       "issues"."last_edited_at",
       "issues"."last_edited_by_id",
       "issues"."discussion_locked",
       "issues"."closed_at",
       "issues"."closed_by_id",
       "issues"."state_id",
       "issues"."duplicated_to_id",
       "issues"."promoted_to_epic_id",
       "issues"."health_status",
       "issues"."external_key",
       "issues"."sprint_id",
       "issues"."blocking_issues_count",
       "issues"."upvotes_count",
       "issues"."work_item_type_id",
       "issues"."namespace_id",
       "issues"."start_date",
       "issues"."imported_from"
FROM "issues"
         LEFT OUTER JOIN milestones ON issues.milestone_id = milestones.id
WHERE (NOT EXISTS (SELECT 1 FROM "banned_users" WHERE (issues.author_id = banned_users.user_id)))
  AND "issues"."project_id" = 278964
  AND "issues"."state_id" = 1
  AND "issues"."milestone_id" IN (SELECT "milestones"."id"
                                  FROM ((SELECT "milestones".* FROM "milestones" WHERE "milestones"."project_id" = 278964)
                                        UNION ALL
                                        (SELECT "milestones".*
                                         FROM "milestones"
                                         WHERE "milestones"."group_id" IN (SELECT "namespaces"."id"
                                                                           FROM "namespaces"
                                                                           WHERE "namespaces"."type" = 'Group'
                                                                             AND "namespaces"."id" = 9970))) milestones
                                  WHERE ("milestones"."state" IN ('active'))
                                    AND (milestones.start_date > CURRENT_DATE)
                                  ORDER BY "milestones"."project_id" ASC, "milestones"."group_id" ASC,
                                           "milestones"."start_date" ASC)
  AND "issues"."work_item_type_id" IN (1, 2, 5)
ORDER BY "issues"."relative_position" ASC NULLS LAST, "issues"."id" ASC
LIMIT 11
Boards Query Raw SQL After (With Started Filter)

SELECT "issues"."id",
       "issues"."title",
       "issues"."author_id",
       "issues"."project_id",
       "issues"."created_at",
       "issues"."updated_at",
       "issues"."description",
       "issues"."milestone_id",
       "issues"."iid",
       "issues"."updated_by_id",
       "issues"."weight",
       "issues"."confidential",
       "issues"."moved_to_id",
       "issues"."due_date",
       "issues"."lock_version",
       "issues"."title_html",
       "issues"."description_html",
       "issues"."time_estimate",
       "issues"."relative_position",
       "issues"."service_desk_reply_to",
       "issues"."cached_markdown_version",
       "issues"."last_edited_at",
       "issues"."last_edited_by_id",
       "issues"."discussion_locked",
       "issues"."closed_at",
       "issues"."closed_by_id",
       "issues"."state_id",
       "issues"."duplicated_to_id",
       "issues"."promoted_to_epic_id",
       "issues"."health_status",
       "issues"."external_key",
       "issues"."sprint_id",
       "issues"."blocking_issues_count",
       "issues"."upvotes_count",
       "issues"."work_item_type_id",
       "issues"."namespace_id",
       "issues"."start_date",
       "issues"."imported_from"
FROM "issues"
         LEFT OUTER JOIN milestones ON issues.milestone_id = milestones.id
WHERE (NOT EXISTS (SELECT 1 FROM "banned_users" WHERE (issues.author_id = banned_users.user_id)))
  AND "issues"."project_id" = 278964
  AND "issues"."state_id" = 2
  AND ("milestones"."state" IN ('active'))
  AND ((milestones.start_date <= CURRENT_DATE OR milestones.start_date IS NULL) AND
       (milestones.due_date IS NULL OR milestones.due_date > CURRENT_DATE) AND
       NOT (milestones.start_date IS NULL AND milestones.due_date IS NULL))
  AND "issues"."work_item_type_id" IN (1, 2, 5)
ORDER BY "issues"."closed_at" DESC NULLS LAST, "issues"."id" DESC
LIMIT 11

Group > Issues Query Raw SQL After (With Upcoming Filter)

SELECT "issues"."id",
       "issues"."title",
       "issues"."author_id",
       "issues"."project_id",
       "issues"."created_at",
       "issues"."updated_at",
       "issues"."description",
       "issues"."milestone_id",
       "issues"."iid",
       "issues"."updated_by_id",
       "issues"."weight",
       "issues"."confidential",
       "issues"."due_date",
       "issues"."moved_to_id",
       "issues"."lock_version",
       "issues"."title_html",
       "issues"."description_html",
       "issues"."time_estimate",
       "issues"."relative_position",
       "issues"."service_desk_reply_to",
       "issues"."cached_markdown_version",
       "issues"."last_edited_at",
       "issues"."last_edited_by_id",
       "issues"."discussion_locked",
       "issues"."closed_at",
       "issues"."closed_by_id",
       "issues"."state_id",
       "issues"."duplicated_to_id",
       "issues"."promoted_to_epic_id",
       "issues"."health_status",
       "issues"."external_key",
       "issues"."sprint_id",
       "issues"."blocking_issues_count",
       "issues"."upvotes_count",
       "issues"."work_item_type_id",
       "issues"."namespace_id",
       "issues"."start_date",
       "issues"."imported_from"
FROM "issues"
         INNER JOIN "projects" ON "projects"."id" = "issues"."project_id"
         LEFT JOIN project_features ON projects.id = project_features.project_id
         LEFT OUTER JOIN milestones ON issues.milestone_id = milestones.id
WHERE "projects"."namespace_id" IN (SELECT namespaces.traversal_ids[array_length(namespaces.traversal_ids, 1)] AS id
                                    FROM "namespaces"
                                    WHERE "namespaces"."type" = 'Group'
                                      AND (traversal_ids @> ('{9970}')))
  AND (EXISTS (SELECT 1
               FROM "project_authorizations"
               WHERE "project_authorizations"."user_id" = 1
                 AND (project_authorizations.project_id = projects.id)) OR projects.visibility_level IN (0, 10, 20))
  AND ("project_features"."issues_access_level" > 0 OR "project_features"."issues_access_level" IS NULL)
  AND "issues"."state_id" = 1
  AND ("issues"."project_id" IS NULL OR "projects"."archived" = FALSE)
  AND "issues"."milestone_id" IN (SELECT "milestones"."id"
                                  FROM ((SELECT "milestones".*
                                         FROM "milestones"
                                         WHERE "milestones"."project_id" IN (SELECT "projects"."id"
                                                                             FROM "projects"
                                                                                      LEFT JOIN project_features ON projects.id = project_features.project_id
                                                                             WHERE "projects"."namespace_id" IN
                                                                                   (SELECT namespaces.traversal_ids[array_length(namespaces.traversal_ids, 1)] AS id
                                                                                    FROM "namespaces"
                                                                                    WHERE "namespaces"."type" = 'Group'
                                                                                      AND (traversal_ids @> ('{9970}')))
                                                                               AND (EXISTS (SELECT 1
                                                                                            FROM "project_authorizations"
                                                                                            WHERE "project_authorizations"."user_id" = 1
                                                                                              AND (project_authorizations.project_id = projects.id)) OR
                                                                                    projects.visibility_level IN (0, 10, 20))
                                                                               AND (
                                                                                 "project_features"."issues_access_level" >
                                                                                 0 OR
                                                                                 "project_features"."issues_access_level" IS NULL)))
                                        UNION ALL
                                        (SELECT "milestones".*
                                         FROM "milestones"
                                         WHERE "milestones"."group_id" = 9970)) milestones
                                  WHERE ("milestones"."state" IN ('active'))
                                    AND (milestones.start_date > CURRENT_DATE)
                                  ORDER BY "milestones"."project_id" ASC, "milestones"."group_id" ASC,
                                           "milestones"."start_date" ASC)
  AND "issues"."work_item_type_id" IN (1, 2, 5, 7, 6, 3)
ORDER BY "issues"."created_at" DESC, "issues"."id" DESC
LIMIT 51

Group > Issues Query Raw SQL After (With Started Filter)


SELECT "issues"."id",
       "issues"."title",
       "issues"."author_id",
       "issues"."project_id",
       "issues"."created_at",
       "issues"."updated_at",
       "issues"."description",
       "issues"."milestone_id",
       "issues"."iid",
       "issues"."updated_by_id",
       "issues"."weight",
       "issues"."confidential",
       "issues"."moved_to_id",
       "issues"."due_date",
       "issues"."lock_version",
       "issues"."title_html",
       "issues"."description_html",
       "issues"."time_estimate",
       "issues"."relative_position",
       "issues"."service_desk_reply_to",
       "issues"."cached_markdown_version",
       "issues"."last_edited_at",
       "issues"."last_edited_by_id",
       "issues"."discussion_locked",
       "issues"."closed_at",
       "issues"."closed_by_id",
       "issues"."state_id",
       "issues"."duplicated_to_id",
       "issues"."promoted_to_epic_id",
       "issues"."health_status",
       "issues"."external_key",
       "issues"."sprint_id",
       "issues"."blocking_issues_count",
       "issues"."upvotes_count",
       "issues"."work_item_type_id",
       "issues"."namespace_id",
       "issues"."start_date",
       "issues"."imported_from"
FROM "issues"
         INNER JOIN "projects" ON "projects"."id" = "issues"."project_id"
         LEFT JOIN project_features ON projects.id = project_features.project_id
         LEFT OUTER JOIN milestones ON issues.milestone_id = milestones.id
WHERE (NOT EXISTS (SELECT 1 FROM "banned_users" WHERE (issues.author_id = banned_users.user_id)))
  AND "projects"."namespace_id" IN (SELECT "namespaces"."id"
                                    FROM UNNEST(COALESCE((SELECT ids
                                                          FROM (SELECT "namespace_descendants"."self_and_descendant_group_ids" AS ids
                                                                FROM "namespace_descendants"
                                                                WHERE "namespace_descendants"."outdated_at" IS NULL
                                                                  AND "namespace_descendants"."namespace_id" = 9970) cached_query),
                                                         (SELECT ids
                                                          FROM (SELECT ARRAY_AGG("namespaces"."id") AS ids
                                                                FROM (SELECT namespaces.traversal_ids[array_length(namespaces.traversal_ids, 1)] AS id
                                                                      FROM "namespaces"
                                                                      WHERE "namespaces"."type" = 'Group'
                                                                        AND (traversal_ids @> ('{9970}'))) namespaces) consistent_query))) AS namespaces(id))
  AND (EXISTS (SELECT 1
               FROM "project_authorizations"
               WHERE "project_authorizations"."user_id" = 25345642
                 AND (project_authorizations.project_id = projects.id)
                 AND (project_authorizations.access_level >= 10)) OR projects.visibility_level IN (10, 20))
  AND ("project_features"."issues_access_level" IS NULL OR "project_features"."issues_access_level" IN (20, 30) OR
       ("project_features"."issues_access_level" = 10 AND EXISTS (SELECT 1
                                                                  FROM "project_authorizations"
                                                                  WHERE "project_authorizations"."user_id" = 25345642
                                                                    AND (project_authorizations.project_id = project_features.project_id)
                                                                    AND (project_authorizations.access_level >= 10))))
  AND "issues"."state_id" = 1
  AND ("issues"."project_id" IS NULL OR "projects"."archived" = FALSE)
  AND ("milestones"."state" IN ('active'))
  AND ((milestones.start_date <= CURRENT_DATE OR milestones.start_date IS NULL) AND
       (milestones.due_date IS NULL OR milestones.due_date > CURRENT_DATE) AND
       NOT (milestones.start_date IS NULL AND milestones.due_date IS NULL))
  AND "issues"."work_item_type_id" IN (1, 2, 5, 7, 6, 3)
ORDER BY "issues"."created_at" ASC, "issues"."id" DESC
LIMIT 21

Query Plans

Before:

Query Type Query Plan
Board with Milestone = %Upcoming (link) pg.ai
Board with Milestone = %Started pg.ai
Group (9970) > Issues page with Milestone = %Upcoming pg.ai
Group (9970) > Issues page with Milestone = %Started pg.ai
Project (278964) > Issues page with Milestone = %Started pg.ai

After:

Query Type Query Plan
Board with Milestone = %Upcoming pg.ai
Board with Milestone = %Started pg.ai
Group (9970) > Issues page with Milestone = %Upcoming pg.ai
Group (9970) > Issues page with Milestone = %Started pg.ai
Project (278964) > Issues page with Milestone = %Started pg.ai

Related to #429728 (closed)

Edited by Matt D'Angelo

Merge request reports

Loading