Repository navigation
Conversation
This was referenced Oct 28, 2026
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
- Read through a Backpex.Query - Run the options query of a field when the options are read - Keep the guides on upgrading from linking removed functions - Build the index query with the index fields in item and resource actions - Sort the options of association fields with :options_sort - Let metrics ignore filters of the index view with :ignore_filters
Flo0807
force-pushed
the
feature/backpex-query
branch
from
November 13, 2026 09:46
6e7ee27 to
a98d1b8
Compare
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stack (merge in this order)
developStep 3 of the data source abstraction: Backpex builds a neutral
%Backpex.Query{}for every read, and the adapter only runs it. Adapters no longer get the fields, filters or criteria of the LiveResource.Query
Backpex.Queryholds what a read needs:from(a path of relationships,[]for the items of the resource),filter(oneBackpex.Expr, already checked and cast withdescribe/2),search(term and target refs),sort/default_sort(refs and directions with nulls),limit,offset,load,computed,aggregates,native(data only the adapter understands),context(%{assigns: assigns}),errorsandvalid?.The builder follows
Ash.Query:new/2,from/2,filter/2(ANDs),primary/2,primary_in/2,search/3,sort/2,default_sort/2,limit/2,offset/2,load/2,compute/3,aggregate/4(named, withwhere:),unset/2,key/1.Adapter contract
get/4,list/4read/1(getisprimary/2+limit(1))count/4count/1metric/5aggregate/1, all aggregates of a query at oncelist_options/4,list_options_by_key/4,count_options/4,options_key/3read/1/count/1withfrom: [field]; equal queries are read once (Query.key/1), and the key replacesoptions_key/3put_field_options/2: the adapter takes the options it adds to fields intoquery.nativeBackpex.Adapters.Ectotranslates its own options input_field_options/2::select(computed values, sorting, search),:custom_aliasand association joins, preload selects,search_condition/3ofBackpex.Adapters.Ecto.Field, and the:options_queryof association fields (evaluated when the query is built, so the key changes with the assigns it depends on).Backpex.Adapters.Ecto.ecto_query/1returns theEcto.Queryof aBackpex.Query, e.g. to stream an export.Core
Backpex.Resource.items_query/3,read/1,read_by_key/1,count/1,aggregate/1,metrics/3,options_query/3.get/4,reload/4,list_options/4,list_options_by_key/4,count_options/4andoptions_key/3keep their signatures and build queries.Backpex.LiveResource.index_query/1(replacesbuild_criteria/1),filter_query/2andfield_ref/1.index_query/1takes the fields of the index view of the LiveResource, so it also works with the assigns of item and resource actions, which have fields of their own (e.g. an export).index_query/2takes given fields; the index view passes its own.c:Backpex.LiveResource.scope/1: an expression every item of the resource matches, for every adapter.:item_querystays for Ecto.:options_filterand:options_sortofBelongsTo,HasManyandHasManyThrough: an expression that the options match and a sort likeBackpex.Query.sort/2, each also as a function of the assigns.:options_querystays for Ecto.c:Backpex.Metric.data/3receives the query of the index view (all pages) instead of criteria. Metrics the adapter computes go to it in oneaggregate/1call. A metric withignore_filters: [:status]ignores these filters of the index view, e.g. to count the items of every status while the index view shows one; metrics that ignore the same filters share a query.:binary_idfields asEcto.UUID, so invalid UUIDs make the query invalid instead of reaching the database.Not in this PR
filter_input/2andsort_input/2from the design doc: the index view already validates filters and sorts from the URL. They follow when a public API needs them.full_text_searchstays a LiveResource option; the Ecto adapter reads it from there.supports?/2, in-memory fallback) and 5 (writes and the form type) follow as their own PRs on top.Review fixes
:selectruns when the options are read again, so its binding is only named for a search, as before. An options query that names its own binding raised. Its result is still part of the key, andQuery.key/1documents that adapters put what their items depend on into:native.Merged with
develop(v0.24.0)The option checks of the relation fields from v0.24.0 run on the query:
Backpex.Query.key_in/3keeps the items whose field is one of the submitted ids (primary_in/2uses it for the primary key), andBackpex.Resource.list_options/4takes a:keycriterion for it. The Ecto adapter keeps alimitoroffsetof the:options_queryin a subquery when the query has a filter, so a submitted id outside the limited options is refused.Testing
On 399a78b:
mix test: 1485 passed (187 doctests, 1298 tests)mix test --only e2e: 60 passedMIX_ENV=test mix lint: cleanOn 8f57af7 (
:ignore_filters,index_query/2,:options_sort; the later merges only change the upgrade guide):mix test: 1488 passed (187 doctests, 1301 tests)MIX_ENV=test mix lint: cleanbun run test51 passed,bun run test:playwright38 passed,bun run lintclean