Update Mutations
Relevant source files
The following files were used as context for generating this wiki page:
Update mutations in Seaography provide a mechanism to modify existing records in a database through the GraphQL API. This feature takes an entity data object along with a filter condition, applies the updates to matching records via SeaORM, and returns the modified entities. It supports advanced features such as lifecycle hooks, guards for access control, and automatic transaction management.
Sources: CHANGELOG.md:162-165, src/lib.rs:58
Architecture and Components
The update mutation system is built around the EntityUpdateMutationBuilder and its configuration. It leverages the dynamic schema capabilities of async-graphql to generate mutation fields for SeaORM entities.
Configuration
The mutation's behavior is governed by the EntityUpdateMutationConfig structure, which defines naming conventions for the mutation and its arguments.
| Field | Type | Default | Description |
|---|---|---|---|
mutation_suffix | String | "Update" or "_update" | Suffix appended to the entity name to form the mutation name. |
data_field | String | "data" | Name of the argument containing the fields to update. |
filter_field | String | "filter" | Name of the argument containing the filter criteria. |
Sources: src/mutation/entity_update_mutation.rs:16-39
Execution Flow
When an update mutation is executed, it follows a structured process:
- Guards: It checks entity-level guards to ensure the user has permission to perform the update.
- Transaction: It starts a database transaction.
- Filter Application: It parses the
filterargument to identify which entities should be updated. - Field Guards: It iterates through the fields provided in the
dataargument and checks field-level guards. - Model Preparation: It converts the input object into a SeaORM
ActiveModel. - Execution: It executes an
update_manystatement. If the database supportsRETURNING(like Postgres), it retrieves the updated models directly; otherwise, it performs a subsequentfindquery within the transaction. - Post-Processing: It triggers
after_savehooks for each updated model. - Watch Hooks: It triggers the
entity_watchhook after a successful commit.
Sources: src/mutation/entity_update_mutation.rs:75-151
The following diagram illustrates the sequence of operations during an update mutation:
Implementation Details
Mutation Field Generation
The to_field method in EntityUpdateMutationBuilder is responsible for creating the async_graphql::dynamic::Field. It defines two primary arguments:
- data: A required input object type corresponding to the entity's fields allowed for update.
- filter: An optional filter input object used to select the target records.
Sources: src/mutation/entity_update_mutation.rs:60-84, src/mutation/entity_update_mutation.rs:155-163
Handling Results and Returns
Update mutations return a list of the modified entities. This is implemented using TypeRef::named_nn_list_nn, ensuring a non-null list of non-null basic entity objects is returned.
Field::new(
self.type_name::<T>(),
TypeRef::named_nn_list_nn(entity_object_builder.basic_type_name::<T>()),
move |ctx| { ... }
)
Sources: src/mutation/entity_update_mutation.rs:86-88
Lifecycle Hooks and Security
Update mutations integrate tightly with Seaography's lifecycle hooks system. This allows developers to inject logic or block operations based on custom rules.
- Entity Guard: Blocks the entire update operation based on the entity and operation type.
- Field Guard: Blocks updates to specific columns.
- Entity Filter: Injects additional conditions (e.g., for multi-tenancy) into the update query.
- After Save: Executes logic for each updated model before the transaction is committed.
Sources: src/mutation/entity_update_mutation.rs:91-140, examples/sea-draw/src/schema.rs:114-142
Examples
GraphQL Mutation Syntax
The following is an example of an update mutation targeting a country entity where the countryId is less than 6.
mutation {
countryUpdate(
data: { country: "[MODIFIED]" }
filter: { countryId: { lt: 6 } }
) {
countryId
country
}
}
Sources: examples/mysql/tests/mutation_tests.rs:360-368, examples/sqlite/tests/mutation_tests.rs:356-364
Data and Filter Mapping
Update mutations utilize Seaography's internal mapping logic to translate GraphQL inputs into SeaORM types. The prepare_active_model function (found in entity_create_one_mutation.rs but utilized by the update builder) handles the conversion of input objects into database-ready active models.
Sources: src/mutation/entity_update_mutation.rs:121-125, src/mutation/entity_create_one_mutation.rs:120-151
Summary
Update Mutations provide a robust, transaction-safe way to modify data in Seaography. By integrating SeaORM's update_many with async-graphql's dynamic schema and a comprehensive lifecycle hook system, it ensures that updates are not only efficient but also compliant with application-level security and business logic.
Sources: src/mutation/entity_update_mutation.rs:88-151, src/lib.rs:58-65