pub struct QueryMatch {
pub query_def: QueryDefinition,
pub fields: Vec<String>,
pub selections: Vec<FieldSelection>,
pub arguments: HashMap<String, Value>,
pub operation_name: Option<String>,
pub scope_where: Option<Value>,
pub search_relevance: Option<RelevanceOrder>,
pub parsed_query: ParsedQuery,
}Expand description
A matched query with extracted information.
Fields§
§query_def: QueryDefinitionThe matched query definition from compiled schema.
fields: Vec<String>Requested fields (selection set) - now includes full field info.
selections: Vec<FieldSelection>Parsed and processed field selections (after fragment/directive resolution).
arguments: HashMap<String, Value>Query arguments/variables.
operation_name: Option<String>Query operation name (if provided).
scope_where: Option<Value>The server’s own row-scoping predicate, in the same
{field: {op: value}} shape a client where uses, or None when the
caller is a plain GraphQL document.
Kept apart from arguments["where"] because the two are not the same
kind of thing and must not share a fate (#1170). REST resource embedding
used to build its parent-scoping join predicate into arguments["where"]
and dispatch it through the ordinary read path — which composes that
argument only when the target query’s auto_params.has_where is set.
has_where governs the client-facing filter surface; a project that
turns it off is saying “clients may not filter this”, not “and relations
that embed it may go unscoped”. Turning it off silently discarded the
predicate and reported the target’s entire result set as the relation’s
contents — every row under every parent, and, on the ManyToOne branch,
the wrong parent attributed outright.
Composed unconditionally alongside RLS and inject_params, which is
where server-side scoping belongs, and never read from client input: a
GraphQL document has no syntax that reaches this field.
search_relevance: Option<RelevanceOrder>The server’s own relevance ordering, derived from a ?search=
request, or None when the read was not a full-text search (#1284).
Kept apart from arguments["orderBy"] for the same reason
scope_where is kept apart from
arguments["where"]: the argument map is the client’s surface, and
this is not something a client can spell. The previous attempt did put it
there — as [{"_relevance": "desc"}] — and it type-checked at the
handler, at serde_json, and at the argument map, failing only in the
ORDER BY parser three layers down, which is how the documented default
path of full-text search answered 400 on every representation.
The transport sets this only when the client named no sort of its own, so
an explicit ?sort= always wins — which is what the generated OpenAPI
document promises (“ranked by relevance unless sort is specified”).
parsed_query: ParsedQueryThe parsed query (for access to fragments, variables, etc.).
Implementations§
Source§impl QueryMatch
impl QueryMatch
Sourcepub fn response_key(&self) -> &str
pub fn response_key(&self) -> &str
The key this query’s result appears under in data.
The document’s alias when it supplies one, otherwise the field name as
written. The envelope used to be keyed by the compiled query
definition’s name, so { a: users { id } } answered under users and two
aliased selections of one query collapsed into a single key.
Falls back to the definition name when there is no selection to read —
the REST transport builds a QueryMatch with no GraphQL document behind
it.
Sourcepub fn from_operation(
query_def: QueryDefinition,
fields: Vec<String>,
arguments: HashMap<String, Value>,
_type_def: Option<&TypeDefinition>,
) -> Result<Self>
pub fn from_operation( query_def: QueryDefinition, fields: Vec<String>, arguments: HashMap<String, Value>, _type_def: Option<&TypeDefinition>, ) -> Result<Self>
Build a QueryMatch directly from a query definition and arguments,
bypassing GraphQL string parsing.
Used by the REST transport to construct sub-queries for resource embedding and bulk operations without synthesising a GraphQL query string.
The result has the same shape as QueryMatcher::match_query’s: a single
root selection named for the query, carrying the requested fields as its
nested_fields. Every consumer of a QueryMatch reads the requested field set
as selections.first().nested_fields — the planner’s projection extraction, the
#423 field-authorization gate, and project_nested_lists all do — so a flat
list of leaf selections reads to all of them as “no fields requested”.
That was #886: this constructor built the flat shape, so every REST read
projected zero fields ({"data":[{},{},{}]}) and the field-authorization gate
was handed an empty slice and never fired. The two defects masked each other —
no gated value leaked only because no value was served at all.
§Errors
Returns FraiseQLError::Validation if the query definition has no SQL source.
Sourcepub fn with_scope_where(self, scope_where: Value) -> Self
pub fn with_scope_where(self, scope_where: Value) -> Self
Attach the server’s own scoping predicate to a QueryMatch built by a
non-GraphQL transport.
See scope_where for why this is not simply another
entry in arguments.
Sourcepub fn with_search_relevance(self, relevance: RelevanceOrder) -> Self
pub fn with_search_relevance(self, relevance: RelevanceOrder) -> Self
Attach the relevance ordering a ?search= request implies (#1284).
See search_relevance for why this is not
another entry in arguments.