Add missing issue due date filters

Merged Lee Tickett requested to merge add-missing-issue-due-date-filters into master

What does this MR do and why?

Adds any, today, and tomorrow issue due_date filters to API.

MR created during pairing session with @espadav8 - thanks Andrew 💪

DB

There are identical and more complex plans for existing queries so we should be good 👌

Details for searching all issues in a project
SELECT COUNT(*) FROM "issues" WHERE "issues"."project_id" = 6 AND "issues"."due_date" = '2022-01-22'

 Aggregate  (cost=3.45..3.46 rows=1 width=8) (actual time=0.041..0.041 rows=1 loops=1)
   Buffers: shared hit=3
   I/O Timings: read=0.000 write=0.000
   ->  Index Only Scan using idx_issues_on_project_id_and_due_date_and_id_and_state_id on public.issues  (cost=0.43..3.45 rows=1 width=0) (actual time=0.036..0.037 rows=0 loops=1)
         Index Cond: ((issues.project_id = 6) AND (issues.due_date = '2022-01-22'::date))
         Heap Fetches: 0
         Buffers: shared hit=3
         I/O Timings: read=0.000 write=0.000

cold:
Time: 1.922 ms
  - planning: 0.343 ms
  - execution: 1.579 ms
    - I/O read: 1.466 ms
    - I/O write: 0.000 ms

Shared buffers:
  - hits: 1 (~8.00 KiB) from the buffer pool
  - reads: 2 (~16.00 KiB) from the OS file cache, including disk I/O
  - dirtied: 0
  - writes: 0

warm:
Time: 0.371 ms
  - planning: 0.290 ms
  - execution: 0.081 ms
    - I/O read: 0.000 ms
    - I/O write: 0.000 ms

Shared buffers:
  - hits: 3 (~24.00 KiB) from the buffer pool
  - reads: 0 from the OS file cache, including disk I/O
  - dirtied: 0
  - writes: 0

SELECT "issues".* FROM "issues" WHERE "issues"."project_id" = 6 AND "issues"."due_date" = '2022-01-22' ORDER BY "issues"."created_at" DESC, "issues"."id" DESC LIMIT 20 OFFSET 0

 Limit  (cost=3.46..3.46 rows=1 width=1417) (actual time=0.042..0.043 rows=0 loops=1)
   Buffers: shared hit=9
   I/O Timings: read=0.000 write=0.000
   ->  Sort  (cost=3.46..3.46 rows=1 width=1417) (actual time=0.040..0.041 rows=0 loops=1)
         Sort Key: issues.created_at DESC, issues.id DESC
         Sort Method: quicksort  Memory: 25kB
         Buffers: shared hit=9
         I/O Timings: read=0.000 write=0.000
         ->  Index Scan using idx_issues_on_project_id_and_due_date_and_id_and_state_id on public.issues  (cost=0.43..3.45 rows=1 width=1417) (actual time=0.020..0.020 rows=0 loops=1)
               Index Cond: ((issues.project_id = 6) AND (issues.due_date = '2022-01-22'::date))
               Buffers: shared hit=3
               I/O Timings: read=0.000 write=0.000


Time: 2.752 ms
  - planning: 2.664 ms
  - execution: 0.088 ms
    - I/O read: 0.000 ms
    - I/O write: 0.000 ms

Shared buffers:
  - hits: 9 (~72.00 KiB) from the buffer pool
  - reads: 0 from the OS file cache, including disk I/O
  - dirtied: 0
  - writes: 0
Details for searching all issues in a group
explain SELECT COUNT(*) FROM "issues" INNER JOIN "projects" ON "projects"."id" = "issues"."project_id" LEFT JOIN project_features ON projects.id = project_features.project_id WHERE "projects"."namespace_id" IN (WITH RECURSIVE "base_and_descendants" AS ((SELECT "namespaces"."id", "namespaces"."name", "namespaces"."path", "namespaces"."owner_id", "namespaces"."created_at", "namespaces"."updated_at", "namespaces"."type", "namespaces"."description", "namespaces"."avatar", "namespaces"."membership_lock", "namespaces"."share_with_group_lock", "namespaces"."visibility_level", "namespaces"."request_access_enabled", "namespaces"."ldap_sync_status", "namespaces"."ldap_sync_error", "namespaces"."ldap_sync_last_update_at", "namespaces"."ldap_sync_last_successful_update_at", "namespaces"."ldap_sync_last_sync_at", "namespaces"."description_html", "namespaces"."lfs_enabled", "namespaces"."parent_id", "namespaces"."shared_runners_minutes_limit", "namespaces"."repository_size_limit", "namespaces"."require_two_factor_authentication", "namespaces"."two_factor_grace_period", "namespaces"."cached_markdown_version", "namespaces"."project_creation_level", "namespaces"."runners_token", "namespaces"."file_template_project_id", "namespaces"."saml_discovery_token", "namespaces"."runners_token_encrypted", "namespaces"."custom_project_templates_group_id", "namespaces"."auto_devops_enabled", "namespaces"."extra_shared_runners_minutes_limit", "namespaces"."last_ci_minutes_notification_at", "namespaces"."last_ci_minutes_usage_notification_level", "namespaces"."subgroup_creation_level", "namespaces"."emails_disabled", "namespaces"."max_pages_size", "namespaces"."max_artifacts_size", "namespaces"."mentions_disabled", "namespaces"."default_branch_protection", "namespaces"."unlock_membership_to_ldap", "namespaces"."max_personal_access_token_lifetime", "namespaces"."push_rule_id", "namespaces"."shared_runners_enabled", "namespaces"."allow_descendants_override_disabled_shared_runners", "namespaces"."traversal_ids" FROM "namespaces" WHERE "namespaces"."type" = 'Group' AND "namespaces"."id" = 9970)
UNION
(SELECT "namespaces"."id", "namespaces"."name", "namespaces"."path", "namespaces"."owner_id", "namespaces"."created_at", "namespaces"."updated_at", "namespaces"."type", "namespaces"."description", "namespaces"."avatar", "namespaces"."membership_lock", "namespaces"."share_with_group_lock", "namespaces"."visibility_level", "namespaces"."request_access_enabled", "namespaces"."ldap_sync_status", "namespaces"."ldap_sync_error", "namespaces"."ldap_sync_last_update_at", "namespaces"."ldap_sync_last_successful_update_at", "namespaces"."ldap_sync_last_sync_at", "namespaces"."description_html", "namespaces"."lfs_enabled", "namespaces"."parent_id", "namespaces"."shared_runners_minutes_limit", "namespaces"."repository_size_limit", "namespaces"."require_two_factor_authentication", "namespaces"."two_factor_grace_period", "namespaces"."cached_markdown_version", "namespaces"."project_creation_level", "namespaces"."runners_token", "namespaces"."file_template_project_id", "namespaces"."saml_discovery_token", "namespaces"."runners_token_encrypted", "namespaces"."custom_project_templates_group_id", "namespaces"."auto_devops_enabled", "namespaces"."extra_shared_runners_minutes_limit", "namespaces"."last_ci_minutes_notification_at", "namespaces"."last_ci_minutes_usage_notification_level", "namespaces"."subgroup_creation_level", "namespaces"."emails_disabled", "namespaces"."max_pages_size", "namespaces"."max_artifacts_size", "namespaces"."mentions_disabled", "namespaces"."default_branch_protection", "namespaces"."unlock_membership_to_ldap", "namespaces"."max_personal_access_token_lifetime", "namespaces"."push_rule_id", "namespaces"."shared_runners_enabled", "namespaces"."allow_descendants_override_disabled_shared_runners", "namespaces"."traversal_ids" FROM "namespaces", "base_and_descendants" WHERE "namespaces"."type" = 'Group' AND "namespaces"."parent_id" = "base_and_descendants"."id")) SELECT "namespaces"."id" FROM "base_and_descendants" AS "namespaces") 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 "projects"."archived" = FALSE AND "issues"."due_date" = '2022-01-22'

 Aggregate  (cost=24916.79..24916.80 rows=1 width=8) (actual time=26.771..26.778 rows=1 loops=1)
   Buffers: shared hit=17208
   I/O Timings: read=0.000 write=0.000
   ->  Nested Loop Left Join  (cost=1553.97..24916.79 rows=1 width=0) (actual time=16.673..26.770 rows=4 loops=1)
         Filter: ((project_features.issues_access_level > 0) OR (project_features.issues_access_level IS NULL))
         Rows Removed by Filter: 0
         Buffers: shared hit=17208
         I/O Timings: read=0.000 write=0.000
         ->  Nested Loop  (cost=1553.54..24916.29 rows=1 width=4) (actual time=16.648..26.714 rows=4 loops=1)
               Buffers: shared hit=17192
               I/O Timings: read=0.000 write=0.000
               ->  Nested Loop  (cost=1553.11..23099.06 rows=3883 width=4) (actual time=3.284..20.179 rows=1641 loops=1)
                     Buffers: shared hit=12264
                     I/O Timings: read=0.000 write=0.000
                     ->  HashAggregate  (cost=1552.54..1554.54 rows=200 width=4) (actual time=3.202..3.290 rows=292 loops=1)
                           Group Key: namespaces.id
                           Buffers: shared hit=1519
                           I/O Timings: read=0.000 write=0.000
                           ->  CTE Scan on base_and_descendants namespaces  (cost=1546.01..1550.03 rows=201 width=4) (actual time=0.047..3.088 rows=292 loops=1)
                                 Buffers: shared hit=1519
                                 I/O Timings: read=0.000 write=0.000
                                 CTE base_and_descendants
                                   ->  Recursive Union  (cost=0.43..1546.01 rows=201 width=358) (actual time=0.045..2.645 rows=292 loops=1)
                                         Buffers: shared hit=1519
                                         I/O Timings: read=0.000 write=0.000
                                         ->  Index Scan using namespaces_pkey on public.namespaces namespaces_1  (cost=0.43..3.46 rows=1 width=358) (actual time=0.037..0.039 rows=1 loops=1)
                                               Index Cond: (namespaces_1.id = 9970)
                                               Filter: ((namespaces_1.type)::text = 'Group'::text)
                                               Rows Removed by Filter: 0
                                               Buffers: shared hit=4
                                               I/O Timings: read=0.000 write=0.000
                                         ->  Nested Loop  (cost=0.56..153.85 rows=20 width=358) (actual time=0.019..0.323 rows=48 loops=6)
                                               Buffers: shared hit=1515
                                               I/O Timings: read=0.000 write=0.000
                                               ->  WorkTable Scan on base_and_descendants  (cost=0.00..0.20 rows=10 width=4) (actual time=0.001..0.005 rows=49 loops=6)
                                                     I/O Timings: read=0.000 write=0.000
                                               ->  Index Scan using index_namespaces_on_parent_id_and_id on public.namespaces namespaces_2  (cost=0.56..15.35 rows=2 width=358) (actual time=0.004..0.006 rows=1 loops=292)
                                                     Index Cond: (namespaces_2.parent_id = base_and_descendants.id)
                                                     Filter: ((namespaces_2.type)::text = 'Group'::text)
                                                     Rows Removed by Filter: 0
                                                     Buffers: shared hit=1515
                                                     I/O Timings: read=0.000 write=0.000
                     ->  Index Scan using index_projects_on_namespace_id_and_id on public.projects  (cost=0.56..107.53 rows=19 width=8) (actual time=0.013..0.057 rows=6 loops=292)
                           Index Cond: (projects.namespace_id = namespaces.id)
                           Filter: ((NOT projects.archived) AND ((alternatives: SubPlan 1 or hashed SubPlan 2) OR (projects.visibility_level = ANY ('{0,10,20}'::integer[]))))
                           Rows Removed by Filter: 0
                           Buffers: shared hit=10745
                           I/O Timings: read=0.000 write=0.000
                           SubPlan 1
                             ->  Index Only Scan using index_project_authorizations_on_project_id_user_id on public.project_authorizations  (cost=0.57..3.59 rows=1 width=0) (actual time=0.007..0.007 rows=1 loops=1641)
                                   Index Cond: ((project_authorizations.project_id = projects.id) AND (project_authorizations.user_id = 1))
                                   Heap Fetches: 164
                                   Buffers: shared hit=7812
                                   I/O Timings: read=0.000 write=0.000
                           SubPlan 2
                             ->  Index Only Scan using project_authorizations_pkey on public.project_authorizations project_authorizations_1  (cost=0.57..228.48 rows=6448 width=4) (actual time=0.000..0.000 rows=0 loops=0)
                                   Index Cond: (project_authorizations_1.user_id = 1)
                                   Heap Fetches: 0
                                   I/O Timings: read=0.000 write=0.000
               ->  Index Only Scan using idx_issues_on_project_id_and_due_date_and_id_and_state_id on public.issues  (cost=0.43..0.46 rows=1 width=4) (actual time=0.004..0.004 rows=0 loops=1641)
                     Index Cond: ((issues.project_id = projects.id) AND (issues.due_date = '2022-01-22'::date))
                     Heap Fetches: 1
                     Buffers: shared hit=4928
                     I/O Timings: read=0.000 write=0.000
         ->  Index Scan using index_project_features_on_project_id on public.project_features  (cost=0.44..0.48 rows=1 width=8) (actual time=0.012..0.012 rows=1 loops=4)
               Index Cond: (project_features.project_id = projects.id)
               Buffers: shared hit=16
               I/O Timings: read=0.000 write=0.000


cold:
Time: 6.065 s
  - planning: 2.207 ms
  - execution: 6.063 s
    - I/O read: 6.000 s
    - I/O write: 0.000 ms

Shared buffers:
  - hits: 10168 (~79.40 MiB) from the buffer pool
  - reads: 7051 (~55.10 MiB) from the OS file cache, including disk I/O
  - dirtied: 105 (~840.00 KiB)
  - writes: 0

warm:
Time: 29.307 ms
  - planning: 2.215 ms
  - execution: 27.092 ms
    - I/O read: 0.000 ms
    - I/O write: 0.000 ms

Shared buffers:
  - hits: 17208 (~134.40 MiB) from the buffer pool
  - reads: 0 from the OS file cache, including disk I/O
  - dirtied: 0
  - writes: 0

SELECT "issues".* FROM "issues" INNER JOIN "projects" ON "projects"."id" = "issues"."project_id" LEFT JOIN project_features ON projects.id = project_features.project_id WHERE "projects"."namespace_id" IN (WITH RECURSIVE "base_and_descendants" AS ((SELECT "namespaces"."id", "namespaces"."name", "namespaces"."path", "namespaces"."owner_id", "namespaces"."created_at", "namespaces"."updated_at", "namespaces"."type", "namespaces"."description", "namespaces"."avatar", "namespaces"."membership_lock", "namespaces"."share_with_group_lock", "namespaces"."visibility_level", "namespaces"."request_access_enabled", "namespaces"."ldap_sync_status", "namespaces"."ldap_sync_error", "namespaces"."ldap_sync_last_update_at", "namespaces"."ldap_sync_last_successful_update_at", "namespaces"."ldap_sync_last_sync_at", "namespaces"."description_html", "namespaces"."lfs_enabled", "namespaces"."parent_id", "namespaces"."shared_runners_minutes_limit", "namespaces"."repository_size_limit", "namespaces"."require_two_factor_authentication", "namespaces"."two_factor_grace_period", "namespaces"."cached_markdown_version", "namespaces"."project_creation_level", "namespaces"."runners_token", "namespaces"."file_template_project_id", "namespaces"."saml_discovery_token", "namespaces"."runners_token_encrypted", "namespaces"."custom_project_templates_group_id", "namespaces"."auto_devops_enabled", "namespaces"."extra_shared_runners_minutes_limit", "namespaces"."last_ci_minutes_notification_at", "namespaces"."last_ci_minutes_usage_notification_level", "namespaces"."subgroup_creation_level", "namespaces"."emails_disabled", "namespaces"."max_pages_size", "namespaces"."max_artifacts_size", "namespaces"."mentions_disabled", "namespaces"."default_branch_protection", "namespaces"."unlock_membership_to_ldap", "namespaces"."max_personal_access_token_lifetime", "namespaces"."push_rule_id", "namespaces"."shared_runners_enabled", "namespaces"."allow_descendants_override_disabled_shared_runners", "namespaces"."traversal_ids" FROM "namespaces" WHERE "namespaces"."type" = 'Group' AND "namespaces"."id" = 26)
UNION
(SELECT "namespaces"."id", "namespaces"."name", "namespaces"."path", "namespaces"."owner_id", "namespaces"."created_at", "namespaces"."updated_at", "namespaces"."type", "namespaces"."description", "namespaces"."avatar", "namespaces"."membership_lock", "namespaces"."share_with_group_lock", "namespaces"."visibility_level", "namespaces"."request_access_enabled", "namespaces"."ldap_sync_status", "namespaces"."ldap_sync_error", "namespaces"."ldap_sync_last_update_at", "namespaces"."ldap_sync_last_successful_update_at", "namespaces"."ldap_sync_last_sync_at", "namespaces"."description_html", "namespaces"."lfs_enabled", "namespaces"."parent_id", "namespaces"."shared_runners_minutes_limit", "namespaces"."repository_size_limit", "namespaces"."require_two_factor_authentication", "namespaces"."two_factor_grace_period", "namespaces"."cached_markdown_version", "namespaces"."project_creation_level", "namespaces"."runners_token", "namespaces"."file_template_project_id", "namespaces"."saml_discovery_token", "namespaces"."runners_token_encrypted", "namespaces"."custom_project_templates_group_id", "namespaces"."auto_devops_enabled", "namespaces"."extra_shared_runners_minutes_limit", "namespaces"."last_ci_minutes_notification_at", "namespaces"."last_ci_minutes_usage_notification_level", "namespaces"."subgroup_creation_level", "namespaces"."emails_disabled", "namespaces"."max_pages_size", "namespaces"."max_artifacts_size", "namespaces"."mentions_disabled", "namespaces"."default_branch_protection", "namespaces"."unlock_membership_to_ldap", "namespaces"."max_personal_access_token_lifetime", "namespaces"."push_rule_id", "namespaces"."shared_runners_enabled", "namespaces"."allow_descendants_override_disabled_shared_runners", "namespaces"."traversal_ids" FROM "namespaces", "base_and_descendants" WHERE "namespaces"."type" = 'Group' AND "namespaces"."parent_id" = "base_and_descendants"."id")) SELECT "namespaces"."id" FROM "base_and_descendants" AS "namespaces") 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 "projects"."archived" = FALSE AND "issues"."due_date" = '2022-01-22' ORDER BY "issues"."created_at" DESC, "issues"."id" DESC LIMIT 20 OFFSET 0

 Limit  (cost=26667.57..26667.57 rows=1 width=1417) (actual time=0.083..0.086 rows=0 loops=1)
   Buffers: shared hit=10
   I/O Timings: read=0.000 write=0.000
   ->  Sort  (cost=26667.57..26667.57 rows=1 width=1417) (actual time=0.082..0.084 rows=0 loops=1)
         Sort Key: issues.created_at DESC, issues.id DESC
         Sort Method: quicksort  Memory: 25kB
         Buffers: shared hit=10
         I/O Timings: read=0.000 write=0.000
         ->  Nested Loop Left Join  (cost=1553.97..26667.56 rows=1 width=1417) (actual time=0.026..0.028 rows=0 loops=1)
               Filter: ((project_features.issues_access_level > 0) OR (project_features.issues_access_level IS NULL))
               Rows Removed by Filter: 0
               Buffers: shared hit=4
               I/O Timings: read=0.000 write=0.000
               ->  Nested Loop  (cost=1553.54..26667.06 rows=1 width=1421) (actual time=0.025..0.027 rows=0 loops=1)
                     Buffers: shared hit=4
                     I/O Timings: read=0.000 write=0.000
                     ->  Nested Loop  (cost=1553.11..23099.06 rows=3883 width=4) (actual time=0.025..0.027 rows=0 loops=1)
                           Buffers: shared hit=4
                           I/O Timings: read=0.000 write=0.000
                           ->  HashAggregate  (cost=1552.54..1554.54 rows=200 width=4) (actual time=0.025..0.026 rows=0 loops=1)
                                 Group Key: namespaces.id
                                 Buffers: shared hit=4
                                 I/O Timings: read=0.000 write=0.000
                                 ->  CTE Scan on base_and_descendants namespaces  (cost=1546.01..1550.03 rows=201 width=4) (actual time=0.023..0.024 rows=0 loops=1)
                                       Buffers: shared hit=4
                                       I/O Timings: read=0.000 write=0.000
                                       CTE base_and_descendants
                                         ->  Recursive Union  (cost=0.43..1546.01 rows=201 width=358) (actual time=0.022..0.023 rows=0 loops=1)
                                               Buffers: shared hit=4
                                               I/O Timings: read=0.000 write=0.000
                                               ->  Index Scan using namespaces_pkey on public.namespaces namespaces_1  (cost=0.43..3.46 rows=1 width=358) (actual time=0.019..0.020 rows=0 loops=1)
                                                     Index Cond: (namespaces_1.id = 26)
                                                     Filter: ((namespaces_1.type)::text = 'Group'::text)
                                                     Rows Removed by Filter: 1
                                                     Buffers: shared hit=4
                                                     I/O Timings: read=0.000 write=0.000
                                               ->  Nested Loop  (cost=0.56..153.85 rows=20 width=358) (actual time=0.001..0.002 rows=0 loops=1)
                                                     I/O Timings: read=0.000 write=0.000
                                                     ->  WorkTable Scan on base_and_descendants  (cost=0.00..0.20 rows=10 width=4) (actual time=0.001..0.001 rows=0 loops=1)
                                                           I/O Timings: read=0.000 write=0.000
                                                     ->  Index Scan using index_namespaces_on_parent_id_and_id on public.namespaces namespaces_2  (cost=0.56..15.35 rows=2 width=358) (actual time=0.000..0.000 rows=0 loops=0)
                                                           Index Cond: (namespaces_2.parent_id = base_and_descendants.id)
                                                           Filter: ((namespaces_2.type)::text = 'Group'::text)
                                                           Rows Removed by Filter: 0
                                                           I/O Timings: read=0.000 write=0.000
                           ->  Index Scan using index_projects_on_namespace_id_and_id on public.projects  (cost=0.56..107.53 rows=19 width=8) (actual time=0.000..0.000 rows=0 loops=0)
                                 Index Cond: (projects.namespace_id = namespaces.id)
                                 Filter: ((NOT projects.archived) AND ((alternatives: SubPlan 1 or hashed SubPlan 2) OR (projects.visibility_level = ANY ('{0,10,20}'::integer[]))))
                                 Rows Removed by Filter: 0
                                 I/O Timings: read=0.000 write=0.000
                                 SubPlan 1
                                   ->  Index Only Scan using index_project_authorizations_on_project_id_user_id on public.project_authorizations  (cost=0.57..3.59 rows=1 width=0) (actual time=0.000..0.000 rows=0 loops=0)
                                         Index Cond: ((project_authorizations.project_id = projects.id) AND (project_authorizations.user_id = 1))
                                         Heap Fetches: 0
                                         I/O Timings: read=0.000 write=0.000
                                 SubPlan 2
                                   ->  Index Only Scan using project_authorizations_pkey on public.project_authorizations project_authorizations_1  (cost=0.57..228.48 rows=6448 width=4) (actual time=0.000..0.000 rows=0 loops=0)
                                         Index Cond: (project_authorizations_1.user_id = 1)
                                         Heap Fetches: 0
                                         I/O Timings: read=0.000 write=0.000
                     ->  Index Scan using idx_issues_on_project_id_and_due_date_and_id_and_state_id on public.issues  (cost=0.43..0.91 rows=1 width=1417) (actual time=0.000..0.000 rows=0 loops=0)
                           Index Cond: ((issues.project_id = projects.id) AND (issues.due_date = '2022-01-22'::date))
                           I/O Timings: read=0.000 write=0.000
               ->  Index Scan using index_project_features_on_project_id on public.project_features  (cost=0.44..0.48 rows=1 width=8) (actual time=0.000..0.000 rows=0 loops=0)
                     Index Cond: (project_features.project_id = projects.id)
                     I/O Timings: read=0.000 write=0.000

Time: 4.911 ms
  - planning: 4.489 ms
  - execution: 0.422 ms
    - I/O read: 0.000 ms
    - I/O write: 0.000 ms

Shared buffers:
  - hits: 10 (~80.00 KiB) from the buffer pool
  - reads: 0 from the OS file cache, including disk I/O
  - dirtied: 0
  - writes: 0
Details for searching all issues (unlikely)
SELECT COUNT(*) FROM "issues" INNER JOIN "projects" ON "projects"."id" = "issues"."project_id" LEFT JOIN project_features ON projects.id = project_features.project_id WHERE (EXISTS (SELECT 1 FROM "project_authorizations" WHERE "project_authorizations"."user_id" = 1933526 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 "projects"."archived" = FALSE AND "issues"."due_date" = '2022-01-21' 

 Aggregate  (cost=93778.07..93778.08 rows=1 width=8) (actual time=39734.782..39734.784 rows=1 loops=1)
   Buffers: shared hit=45464 read=46372 dirtied=2164
   I/O Timings: read=39012.844 write=0.000
   ->  Nested Loop Left Join  (cost=1.30..93770.22 rows=3141 width=0) (actual time=863.558..39726.191 rows=4430 loops=1)
         Filter: ((project_features.issues_access_level > 0) OR (project_features.issues_access_level IS NULL))
         Rows Removed by Filter: 1
         Buffers: shared hit=45464 read=46372 dirtied=2164
         I/O Timings: read=39012.844 write=0.000
         ->  Nested Loop  (cost=0.87..92190.18 rows=3196 width=4) (actual time=858.048..35133.903 rows=4431 loops=1)
               Buffers: shared hit=31889 read=42223 dirtied=2089
               I/O Timings: read=34494.127 write=0.000
               ->  Index Only Scan using idx_issues_on_project_id_and_due_date_and_id_and_state_id on public.issues  (cost=0.43..69232.14 rows=3266 width=4) (actual time=842.243..28186.917 rows=4434 loops=1)
                     Index Cond: (issues.due_date = '2022-01-21'::date)
                     Heap Fetches: 5260
                     Buffers: shared hit=4099 read=34364 dirtied=1583
                     I/O Timings: read=27754.661 write=0.000
               ->  Index Scan using projects_pkey on public.projects  (cost=0.44..7.03 rows=1 width=4) (actual time=1.561..1.561 rows=1 loops=4434)
                     Index Cond: (projects.id = issues.project_id)
                     Filter: ((NOT projects.archived) AND ((alternatives: SubPlan 1 or hashed SubPlan 2) OR (projects.visibility_level = ANY ('{0,10,20}'::integer[]))))
                     Rows Removed by Filter: 0
                     Buffers: shared hit=27655 read=7859 dirtied=371
                     I/O Timings: read=6739.466 write=0.000
                     SubPlan 1
                       ->  Index Only Scan using index_project_authorizations_on_project_id_user_id on public.project_authorizations  (cost=0.57..3.59 rows=1 width=0) (actual time=0.887..0.887 rows=0 loops=4431)
                             Index Cond: ((project_authorizations.project_id = projects.id) AND (project_authorizations.user_id = 1933526))
                             Heap Fetches: 1
                             Buffers: shared hit=14284 read=3446
                             I/O Timings: read=3872.822 write=0.000
                     SubPlan 2
                       ->  Index Only Scan using project_authorizations_pkey on public.project_authorizations project_authorizations_1  (cost=0.57..216.79 rows=6406 width=4) (actual time=0.000..0.000 rows=0 loops=0)
                             Index Cond: (project_authorizations_1.user_id = 1933526)
                             Heap Fetches: 0
                             I/O Timings: read=0.000 write=0.000
         ->  Index Scan using index_project_features_on_project_id on public.project_features  (cost=0.44..0.48 rows=1 width=8) (actual time=1.033..1.033 rows=1 loops=4431)
               Index Cond: (project_features.project_id = projects.id)
               Buffers: shared hit=13575 read=4149 dirtied=75
               I/O Timings: read=4518.717 write=0.000

cold:
Time: 39.745 s
  - planning: 10.393 ms
  - execution: 39.735 s
    - I/O read: 39.013 s
    - I/O write: 0.000 ms

Shared buffers:
  - hits: 45464 (~355.20 MiB) from the buffer pool
  - reads: 46372 (~362.30 MiB) from the OS file cache, including disk I/O
  - dirtied: 2164 (~16.90 MiB)
  - writes: 0

warm:
Time: 201.422 ms
  - planning: 1.956 ms
  - execution: 199.466 ms
    - I/O read: 0.000 ms
    - I/O write: 0.000 ms

Shared buffers:
  - hits: 89947 (~702.70 MiB) from the buffer pool
  - reads: 0 from the OS file cache, including disk I/O
  - dirtied: 0
  - writes: 0

SELECT "issues".* FROM "issues" INNER JOIN "projects" ON "projects"."id" = "issues"."project_id" LEFT JOIN project_features ON projects.id = project_features.project_id WHERE (EXISTS (SELECT 1 FROM "project_authorizations" WHERE "project_authorizations"."user_id" = 1933526 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 "projects"."archived" = FALSE AND "issues"."due_date" = '2022-01-21' ORDER BY "issues"."created_at" DESC, "issues"."id" DESC LIMIT 20 OFFSET 0

 Limit  (cost=98125.19..98125.24 rows=20 width=1418) (actual time=2475.253..2475.263 rows=20 loops=1)
   Buffers: shared hit=86493 read=1956
   I/O Timings: read=2208.665 write=0.000
   ->  Sort  (cost=98125.19..98133.04 rows=3141 width=1418) (actual time=2475.251..2475.257 rows=20 loops=1)
         Sort Key: issues.created_at DESC, issues.id DESC
         Sort Method: top-N heapsort  Memory: 77kB
         Buffers: shared hit=86493 read=1956
         I/O Timings: read=2208.665 write=0.000
         ->  Nested Loop Left Join  (cost=1.30..98041.61 rows=3141 width=1418) (actual time=2.882..2466.080 rows=4430 loops=1)
               Filter: ((project_features.issues_access_level > 0) OR (project_features.issues_access_level IS NULL))
               Rows Removed by Filter: 1
               Buffers: shared hit=86487 read=1956
               I/O Timings: read=2208.665 write=0.000
               ->  Nested Loop  (cost=0.87..96461.58 rows=3196 width=1422) (actual time=2.869..2437.817 rows=4431 loops=1)
                     Buffers: shared hit=68763 read=1956
                     I/O Timings: read=2208.665 write=0.000
                     ->  Index Scan using idx_issues_on_project_id_and_due_date_and_id_and_state_id on public.issues  (cost=0.43..73503.53 rows=3266 width=1418) (actual time=2.792..2366.900 rows=4434 loops=1)
                           Index Cond: (issues.due_date = '2022-01-21'::date)
                           Buffers: shared hit=33297 read=1956
                           I/O Timings: read=2208.665 write=0.000
                     ->  Index Scan using projects_pkey on public.projects  (cost=0.44..7.03 rows=1 width=4) (actual time=0.014..0.014 rows=1 loops=4434)
                           Index Cond: (projects.id = issues.project_id)
                           Filter: ((NOT projects.archived) AND ((alternatives: SubPlan 1 or hashed SubPlan 2) OR (projects.visibility_level = ANY ('{0,10,20}'::integer[]))))
                           Rows Removed by Filter: 0
                           Buffers: shared hit=35466
                           I/O Timings: read=0.000 write=0.000
                           SubPlan 1
                             ->  Index Only Scan using index_project_authorizations_on_project_id_user_id on public.project_authorizations  (cost=0.57..3.59 rows=1 width=0) (actual time=0.006..0.006 rows=0 loops=4431)
                                   Index Cond: ((project_authorizations.project_id = projects.id) AND (project_authorizations.user_id = 1933526))
                                   Heap Fetches: 1
                                   Buffers: shared hit=17730
                                   I/O Timings: read=0.000 write=0.000
                           SubPlan 2
                             ->  Index Only Scan using project_authorizations_pkey on public.project_authorizations project_authorizations_1  (cost=0.57..216.79 rows=6406 width=4) (actual time=0.000..0.000 rows=0 loops=0)
                                   Index Cond: (project_authorizations_1.user_id = 1933526)
                                   Heap Fetches: 0
                                   I/O Timings: read=0.000 write=0.000
               ->  Index Scan using index_project_features_on_project_id on public.project_features  (cost=0.44..0.48 rows=1 width=8) (actual time=0.005..0.005 rows=1 loops=4431)
                     Index Cond: (project_features.project_id = projects.id)
                     Buffers: shared hit=17724
                     I/O Timings: read=0.000 write=0.000

cold:
Time: 2.480 s
  - planning: 4.175 ms
  - execution: 2.475 s
    - I/O read: 2.209 s
    - I/O write: 0.000 ms

Shared buffers:
  - hits: 86493 (~675.70 MiB) from the buffer pool
  - reads: 1956 (~15.30 MiB) from the OS file cache, including disk I/O
  - dirtied: 0
  - writes: 0

warm:
Time: 192.688 ms
  - planning: 1.646 ms
  - execution: 191.042 ms
    - I/O read: 0.000 ms
    - I/O write: 0.000 ms

Shared buffers:
  - hits: 88449 (~691.00 MiB) from the buffer pool
  - reads: 0 from the OS file cache, including disk I/O
  - dirtied: 0
  - writes: 0

How to set up and validate locally

Assign some due dates to some issues e.g.
"TODAY"- http://gdk.test:3000/flightjs/Flight/-/issues/36
"TOMORROW"- http://gdk.test:3000/flightjs/Flight/-/issues/35

Hit the API to see if the right issues are returned:
`#35` and `#36`- http://gdk.test:3000/api/v4/projects/6/issues?due_date=any
`#36`- http://gdk.test:3000/api/v4/projects/6/issues?due_date=today
`#35`- http://gdk.test:3000/api/v4/projects/6/issues?due_date=tomorrow

`#35` and `#36`- http://gdk.test:3000/api/v4/groups/26/issues?due_date=any
`#36`- http://gdk.test:3000/api/v4/groups/26/issues?due_date=today
`#35`- http://gdk.test:3000/api/v4/groups/26/issues?due_date=tomorrow

`#35` and `#36`- http://gdk.test:3000/api/v4/issues?due_date=any&scope=all
`#36`- http://gdk.test:3000/api/v4/issues?due_date=today&scope=all
`#35`- http://gdk.test:3000/api/v4/issues?due_date=tomorrow&scope=all

MR acceptance checklist

This checklist encourages us to confirm any changes have been analyzed to reduce risks in quality, performance, reliability, security, and maintainability.

Edited by Lee Tickett