Skip to main content

MutationDefinition

Struct MutationDefinition 

Source
pub struct MutationDefinition {
Show 18 fields pub name: String, pub return_type: String, pub arguments: Vec<ArgumentDefinition>, pub description: Option<String>, pub operation: MutationOperation, pub deprecation: Option<DeprecationInfo>, pub sql_source: Option<String>, pub inject_params: IndexMap<String, InjectedParamSource>, pub invalidates_fact_tables: Vec<String>, pub invalidates_views: Vec<String>, pub rest_path: Option<String>, pub rest_method: Option<String>, pub upsert_function: Option<String>, pub requires_role: Option<String>, pub changelog: bool, pub input_style: InputStyle, pub changelog_pre_image: bool, pub cascade: bool,
}
Expand description

A mutation definition compiled from @fraiseql.mutation.

Mutations are declarative bindings to database functions. They describe which function to call, not arbitrary logic.

§Example

use fraiseql_core::schema::{MutationDefinition, MutationOperation};

let mutation = MutationDefinition::new("createUser", "User");

Fields§

§name: String

Mutation name (e.g., “createUser”).

§return_type: String

Return type name.

§arguments: Vec<ArgumentDefinition>

Input arguments.

§description: Option<String>

Description.

§operation: MutationOperation

SQL operation type.

§deprecation: Option<DeprecationInfo>

Deprecation information (from @deprecated directive). When set, this mutation is marked as deprecated in the schema.

§sql_source: Option<String>

PostgreSQL function name to call for this mutation.

When set, the runtime calls SELECT * FROM {sql_source}($1, $2, ...) with the mutation arguments in ArgumentDefinition order, and parses the result as an app.mutation_response composite row.

§inject_params: IndexMap<String, InjectedParamSource>

Server-side parameters injected from JWT claims at runtime.

Keys are SQL parameter names. Values describe where to source the runtime value. These params are NOT exposed as GraphQL arguments.

For mutations: injected params are appended to the positional function call args after client-provided arguments, in map insertion order. The SQL function signature must declare the injected parameters last.

Works on PostgreSQL, SQL Server, and MySQL. SQLite has no stored-routine mechanism and will return an error if inject is configured on a mutation.

§invalidates_fact_tables: Vec<String>

Fact tables whose version counter should be bumped after this mutation succeeds.

When the mutation PostgreSQL function returns successfully, the runtime calls SELECT bump_tf_version($1) for each listed table, incrementing the version used in fact-table cache keys. This ensures that analytic/aggregate queries backed by FactTableVersionStrategy::VersionTable are automatically invalidated.

Each entry must be a valid SQL identifier validated at compile time.

§Example

@fraiseql.mutation(
    sql_source="fn_create_order",
    invalidates_fact_tables=["tf_sales", "tf_order_count"],
)
def create_order(amount: Decimal) -> Order: ...
§invalidates_views: Vec<String>

View names whose cached query results should be invalidated after this mutation succeeds.

When the CachedDatabaseAdapter is active, the runtime calls invalidate_views() with these names, clearing all cache entries that read from the specified views.

If empty and the mutation return type has a sql_source, the runtime infers the primary view from the return type.

Each entry must be a valid SQL identifier validated at compile time.

§rest_path: Option<String>

Custom REST path override (e.g., "/users/{id}").

§rest_method: Option<String>

REST HTTP method override (e.g., "POST", "PUT", "PATCH").

§upsert_function: Option<String>

PostgreSQL upsert function name for PUT semantics (insert-or-update).

§requires_role: Option<String>

Role required to execute this mutation and see it in introspection.

When set, only users whose SecurityContext.roles contains this role can discover and execute the mutation. Others receive "Unknown mutation" (not FORBIDDEN) to prevent role enumeration — mirroring QueryDefinition::requires_role.

§changelog: bool

Whether a successful run of this mutation writes a Change-Spine change-log row (default true).

Composes as a logical AND with the global RuntimeConfig.changelog_enabled: a row is written only when the global switch is on and this flag is true. Set false to opt a single mutation out of the in-transaction outbox write — e.g. a hot endpoint that need not appear in the Change Spine — while leaving the rest of the schema logging. Serde-defaults to true, so a compiled schema produced before this field existed keeps logging.

§input_style: InputStyle

How the GraphQL input argument is passed to the SQL function: Flatten (positional columns, the default) or Jsonb (the whole input as one jsonb arg).

Orthogonal to operation: jsonb forces the single-JSONB-argument path regardless of the DML verb, so an Insert/Delete/Custom mutation backed by a single-jsonb-wrapper function (fn(input_payload jsonb, …)) keeps its real verb — and the Change Spine records the true modification_type — while still receiving the whole input as one argument. Update mutations always take the single-JSONB path whatever this is set to.

Defaults to flatten; an absent value is byte-identical to the behavior before this field existed (so it adds no compiled-schema bytes and does not churn the codegen schema hash).

§changelog_pre_image: bool

Whether a successful, state-changing run of this mutation also records the changed entity’s pre-image (before-state) into the Change-Spine object_data_before column, alongside the after-image it already writes to object_data. Default false.

The pre-image is sourced from an optional entity_before on the mutation’s app.mutation_response (the same way the after-image is sourced from entity); the outbox CTE reads r.entity_before only when this is set, so an opted-in mutation’s response type must expose that column.

Opt-in per mutation so the audit cost (extra storage + a backend that computes the pre-mutation snapshot) is paid only by the audit-sensitive mutations that need an inline Debezium-style {before, after} on the single event — most consumers react to the after-state, and an update’s before-state is the previous row’s after-state, reconstructable from the seq-ordered stream.

Defaults to false; an absent value is byte-identical to the behavior before this field existed (so it adds no compiled-schema bytes and does not churn the codegen schema hash).

§cascade: bool

Whether this mutation exposes and enforces the typed graphql-cascade cascade field on its success payload. Default false.

When true, the runtime surfaces a typed, selection-gated cascade field — mutation responses carrying all affected entities, per the graphql-cascade spec — whose entities are projected to camelCase and run through the field-level authorizer (#423), exactly like a queried entity. When false, no cascade surface exists and any cascade the SQL function returns is ignored.

Set via the authoring SDK’s @fraiseql.type(crud=True, cascade=True) (or @fraiseql.mutation(cascade=True)); before this field existed the compiler silently dropped that flag.

Defaults to false; an absent value is byte-identical to the behavior before this field existed (so it adds no compiled-schema bytes and does not churn the codegen schema hash).

Implementations§

Source§

impl MutationDefinition

Source

pub fn new(name: impl Into<String>, return_type: impl Into<String>) -> Self

Create a new mutation definition.

Source

pub fn deprecated(self, reason: Option<String>) -> Self

Mark this mutation as deprecated.

§Example
use fraiseql_core::schema::MutationDefinition;

let mutation = MutationDefinition::new("oldCreateUser", "User")
    .deprecated(Some("Use 'createUser' instead".to_string()));
assert!(mutation.is_deprecated());
Source

pub const fn is_deprecated(&self) -> bool

Check if this mutation is deprecated.

Source

pub fn deprecation_reason(&self) -> Option<&str>

Get the deprecation reason if deprecated.

Trait Implementations§

Source§

impl Clone for MutationDefinition

Source§

fn clone(&self) -> MutationDefinition

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for MutationDefinition

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<'de> Deserialize<'de> for MutationDefinition

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl PartialEq for MutationDefinition

Source§

fn eq(&self, other: &MutationDefinition) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl Serialize for MutationDefinition

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more
Source§

impl StructuralPartialEq for MutationDefinition

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more