asobi_ops_filters (asobi v0.84.0)

View Source

The WHERE clauses an ops list endpoint builds from its query string.

Each endpoint declares a spec list and this builds the query, so the rules below hold everywhere rather than once per module:

  • An absent or empty filter narrows nothing. A caller can see that: it gets a superset and the rows to prove it.
  • A filter whose value cannot be the shape its column holds - a player_id that is not a uuid - is a 400, not a dropped clause. Dropping it would answer a request scoped to one player with every player's rows, and that is the failure a caller cannot see.
  • An oversized exact-match value is dropped rather than rejected, which is what these endpoints did before this module existed.
  • ilike patterns come from asobi_ops_params:like_pattern/2, so % and _ inside a search term match literally instead of turning the search into a scan of the whole table.

Compare asobi_ops_params:sort/3, which rejects an unknown field: a wrong sort returns a page silently ordered by something else, which no response body reveals.

Summary

Functions

Apply Specs to Query in order, resolving each against Params.

Types

kind()

-type kind() :: equals | boolean | uuid | ilike.

spec()

-type spec() :: {binary(), atom() | [atom()], kind()}.

Functions

build/3

-spec build(#kura_query{from :: atom() | module() | undefined,
                        select :: [atom() | term()] | {exprs, [term()]},
                        wheres :: [term()],
                        joins :: [term()],
                        order_bys :: [term()],
                        group_bys :: [atom()],
                        havings :: [term()],
                        limit :: non_neg_integer() | undefined,
                        offset :: non_neg_integer() | undefined,
                        distinct :: boolean() | [atom()],
                        lock :: binary() | undefined,
                        prefix :: binary() | undefined,
                        preloads :: [atom() | {atom(), list()}],
                        ctes :: [{binary(), #kura_query{}}],
                        combinations :: [{union | union_all | intersect | except, #kura_query{}}],
                        include_deleted :: boolean()},
            asobi_ops_params:params(),
            [spec()]) ->
               {ok,
                #kura_query{from :: atom() | module() | undefined,
                            select :: [atom() | term()] | {exprs, [term()]},
                            wheres :: [term()],
                            joins :: [term()],
                            order_bys :: [term()],
                            group_bys :: [atom()],
                            havings :: [term()],
                            limit :: non_neg_integer() | undefined,
                            offset :: non_neg_integer() | undefined,
                            distinct :: boolean() | [atom()],
                            lock :: binary() | undefined,
                            prefix :: binary() | undefined,
                            preloads :: [atom() | {atom(), list()}],
                            ctes :: [{binary(), #kura_query{}}],
                            combinations :: [{union | union_all | intersect | except, #kura_query{}}],
                            include_deleted :: boolean()}} |
               {error, {invalid_filter, binary()}}.

Apply Specs to Query in order, resolving each against Params.

Named build rather than apply so it cannot be read as the BIF.