{"id":29112062,"url":"https://github.com/jechol/ash_many_to_many_sort_bug","last_synced_at":"2025-09-13T22:07:45.641Z","repository":{"id":300582462,"uuid":"1006537444","full_name":"jechol/ash_many_to_many_sort_bug","owner":"jechol","description":null,"archived":false,"fork":false,"pushed_at":"2025-06-22T14:24:02.000Z","size":21,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-06-22T15:20:28.951Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Elixir","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jechol.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-06-22T13:49:03.000Z","updated_at":"2025-06-22T14:24:06.000Z","dependencies_parsed_at":"2025-06-22T15:20:45.654Z","dependency_job_id":"ea9734c4-7a46-40aa-a784-5236d572999d","html_url":"https://github.com/jechol/ash_many_to_many_sort_bug","commit_stats":null,"previous_names":["jechol/ash_many_to_many_sort_bug"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/jechol/ash_many_to_many_sort_bug","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jechol%2Fash_many_to_many_sort_bug","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jechol%2Fash_many_to_many_sort_bug/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jechol%2Fash_many_to_many_sort_bug/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jechol%2Fash_many_to_many_sort_bug/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jechol","download_url":"https://codeload.github.com/jechol/ash_many_to_many_sort_bug/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jechol%2Fash_many_to_many_sort_bug/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":262574130,"owners_count":23330779,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-06-29T10:04:31.476Z","updated_at":"2025-06-29T10:04:32.970Z","avatar_url":"https://github.com/jechol.png","language":"Elixir","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Ash many_to_many sort bug\n\n## Symptoms\n\nPost has a many_to_many relationship with tags, which is a sorted list of Tags based on the position attribute of the join table PostTag.\n\n```elixir\n    many_to_many :tags, MyDomain.Tag do\n      public? true\n      through MyDomain.PostTag\n      join_relationship :post_tags\n      sort [Ash.Sort.expr_sort(post_tags.position)]\n    end\n```\n\nWhen the Post and PostTag tables are empty, it shows properly sorted results,\nbut when there are other Posts and PostTags, there is a bug where the sort doesn't work correctly.\n\n## Reproduction Method\n\n### Failing Test\nThere is a failing test that can be confirmed with\n```shell\n$ mix setup\n$ mix test\n```\n\n### Seeding the failing case in dev database\n```shell\n$ mix setup\n$ mix ecto.reset\n```\n\nI've set it up to display queries that show the symptoms as follows.\n\n```\n22:48:10.315 [error] Below query is not working as expected. (post.id: 2)\n\n22:48:10.367 [debug] QUERY OK source=\"posts\" db=1.6ms\nSELECT DISTINCT p0.\"id\", s1.\"id\", s1.\"__order__\" FROM \"public\".\"posts\" AS p0 INNER JOIN LATERAL (SELECT DISTINCT ON (st0.\"id\") st0.\"id\" AS \"id\", row_number() OVER \"order\" AS \"__order__\" FROM \"public\".\"tags\" AS st0 INNER JOIN \"public\".\"post_tags\" AS sp1 ON st0.\"id\" = sp1.\"tag_id\" INNER JOIN \"public\".\"post_tags\" AS sp2 ON sp2.\"tag_id\" = st0.\"id\" WHERE (sp2.\"post_id\" = p0.\"id\") WINDOW \"order\" AS (ORDER BY sp1.\"position\"::bigint) ORDER BY st0.\"id\", sp1.\"position\"::bigint) AS s1 ON TRUE WHERE (p0.\"id\"::bigint = ANY('{2}'::bigint[])) AND (p0.\"id\" = ANY('{2}')) ORDER BY s1.\"__order__\"\n\n22:48:10.368 [error] Expected tags are [\"tag1\", \"tag3\", \"tag5\", \"tag4\", \"tag2\"].\n\n22:48:10.368 [error] Result tags are [\"tag1\", \"tag2\", \"tag3\", \"tag5\", \"tag4\"].\n```\n\n## Estimated Cause\n\nWhen beautifying the query displayed during `mix ecto.reset`, it looks like this:\n\n```sql\nSELECT DISTINCT\n  p0.\"id\",\n  s1.\"id\",\n  s1.\"__order__\"\nFROM\n  \"public\".\"posts\" AS p0\n  INNER JOIN LATERAL (\n    SELECT DISTINCT\n      ON (st0.\"id\") st0.\"id\" AS \"id\",\n      row_number() OVER \"order\" AS \"__order__\"\n    FROM\n      \"public\".\"tags\" AS st0\n      INNER JOIN \"public\".\"post_tags\" AS sp1 ON st0.\"id\" = sp1.\"tag_id\" --- (1)\n      INNER JOIN \"public\".\"post_tags\" AS sp2 ON sp2.\"tag_id\" = st0.\"id\" --- (2)\n    WHERE\n      (sp2.\"post_id\" = p0.\"id\") --- (3)\n    WINDOW\n      \"order\" AS (\n        ORDER BY\n          sp1.\"position\"::bigint\n      )\n    ORDER BY\n      st0.\"id\",\n      sp1.\"position\"::bigint\n  ) AS s1 ON TRUE\nWHERE\n  (p0.\"id\"::bigint = ANY ('{2}'::BIGINT[]))\n  AND (p0.\"id\" = ANY ('{2}'))\nORDER BY\n  s1.\"__order__\"\n```\n\nThe post_tags `sp2` joined in (2) is filtered by the corresponding post id in (3),\nbut the post_tags `sp1` joined in (1) is not filtered, causing joins with post ids that are different.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjechol%2Fash_many_to_many_sort_bug","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjechol%2Fash_many_to_many_sort_bug","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjechol%2Fash_many_to_many_sort_bug/lists"}