Skip to main content

Mutations

Hugr automatically generates mutation operations for tables (not views). These mutations handle data modifications with support for relationships, transactions, and returning affected data.

Insert Mutations

Insert single or multiple records:

mutation {
insert_customers(data: {
name: "John Doe"
email: "john@example.com"
status: "active"
}) {
id
name
email
created_at
}
}

Batch Inserts

Insert multiple records in a single mutation:

mutation {
insert_products(data: [
{ name: "Product A", price: 99.99 }
{ name: "Product B", price: 149.99 }
]) {
id
name
price
}
}

Insert with Relations

Insert related records in a single transaction:

mutation {
insert_customers(data: {
name: "Jane Smith"
email: "jane@example.com"
addresses: [
{
street: "123 Main St"
city: "New York"
type: "billing"
}
{
street: "456 Oak Ave"
city: "Boston"
type: "shipping"
}
]
orders: [
{
order_date: "2024-01-15"
status: "pending"
order_details: [
{
product_id: 1
quantity: 2
unit_price: 50.00
}
]
}
]
}) {
id
name
addresses {
id
type
city
}
orders {
id
status
order_details {
product_id
quantity
}
}
}
}

Return Values

For tables with primary keys, the mutation returns the inserted record(s). Without primary keys, it returns an OperationResult:

type OperationResult {
affected_rows: Int!
success: Boolean!
message: String
last_id: BigInt
}

Update Mutations

Update records matching filter conditions:

mutation {
update_customers(
filter: { id: { eq: 123 } }
data: {
email: "newemail@example.com"
updated_at: "2024-01-15T10:00:00Z"
}
) {
affected_rows
success
message
}
}

Bulk Updates

Update multiple records:

mutation {
update_products(
filter: {
category_id: { eq: 5 }
status: { eq: "active" }
}
data: {
discount_percentage: 15
sale_ends_at: "2024-02-01T00:00:00Z"
}
) {
affected_rows
success
}
}

Conditional Updates

Use complex filters for targeted updates:

mutation {
update_orders(
filter: {
_and: [
{ status: { eq: "pending" } }
{ created_at: { lt: "2024-01-01" } }
{ customer: { status: { eq: "active" } } }
]
}
data: {
status: "cancelled"
cancelled_reason: "Order expired"
}
) {
affected_rows
}
}

Delete Mutations

Delete records matching filter conditions:

mutation {
delete_customers(
filter: { id: { eq: 123 } }
) {
affected_rows
success
message
}
}

Bulk Deletes

Delete multiple records:

mutation {
delete_old_logs(
filter: {
created_at: { lt: "2023-01-01" }
}
) {
affected_rows
}
}

Soft Delete

For tables with soft delete enabled:

mutation {
delete_customers(
filter: { id: { eq: 123 } }
) {
affected_rows # Record marked as deleted, not physically removed
}
}

To query including soft-deleted records:

query {
customers @with_deleted {
id
name
deleted_at
}
}

Input Types

Insert Input Type

Generated for each table, includes all fields and relations:

input customers_mut_input_data {
# Direct fields
name: String!
email: String!
status: String

# Related records (one-to-one/many-to-one)
profile: customer_profiles_mut_input_data

# Related records (one-to-many)
addresses: [customer_addresses_mut_input_data]
orders: [orders_mut_input_data]
}

Update Input Type

Contains only direct fields (no relations):

input customers_mut_data {
name: String
email: String
status: String
updated_at: Timestamp
}

Transaction Behavior

All mutations within a single GraphQL request execute in a transaction:

mutation ComplexTransaction {
# All operations succeed or fail together
update_inventory: update_products(
filter: { id: { eq: 100 } }
data: { stock: 45 }
) {
affected_rows
}

create_order: insert_orders(data: {
customer_id: 50
product_id: 100
quantity: 5
}) {
id
}

update_customer: update_customers(
filter: { id: { eq: 50 } }
data: { last_order_date: "2024-01-15" }
) {
affected_rows
}
}

Auto-Generated Values

Sequences

For fields with sequences:

type orders @table(name: "orders") {
id: BigInt! @pk @default(sequence: "orders_id_seq")
order_number: Int! @default(sequence: "order_number_seq")
}

The ID fields are auto-populated during insert.

Default Values

Fields with default values are optional in mutations:

type customers @table(name: "customers") {
status: String! @default(value: "pending")
created_at: Timestamp! @default(value: "NOW()")
}

Error Handling

Mutations return errors in the standard GraphQL error format:

{
"errors": [
{
"message": "Unique constraint violation",
"extensions": {
"code": "UNIQUE_VIOLATION",
"constraint": "customers_email_key"
}
}
]
}