Mutations Insert, update, connect, validate, and transact across related tables. core reference core/mutations core/mutations.md

Mutations

Insert, update, connect, validate, and transact across related tables.

Inserts

GraphQL
mutation {
  users(insert: $data) {
    id
    email
  }
}
Verified by Example_insert tests/insert_test.go:16

Bulk and nested inserts

GraphJin can insert multiple rows and insert across related tables. PostgreSQL uses atomic CTE chains; other dialects use the dialect-appropriate mutation strategy.

GraphQL
mutation {
  products(insert: [
    { id: 5001, name: "Desk", price: 199.00 }
    { id: 5002, name: "Lamp", price: 39.00 }
  ]) {
    id
    name
  }
}
GraphQL
mutation {
  users(insert: $user) {
    id
    products(insert: $products) {
      id
      name
    }
  }
}

Verified by Example_insertInlineBulk tests/insert_test.go:148
Verified by Example_insertIntoMultipleRelatedTables tests/insert_test.go:278

Connect to existing rows

Use connect operations when a mutation should link to existing related records instead of creating new ones.

GraphQL
mutation {
  products(insert: $product) {
    id
    categories(connect: { id: { in: [1, 2] } }) {
      id
      name
    }
  }
}
Verified by Example_insertIntoTableAndConnectToRelatedTables tests/insert_test.go:531

Validation and presets

Mutation validation supports required fields, formats, min/max constraints, comparisons, and conditional requirements. Presets can inject server-controlled values.

Verified by Example_insertInlineWithValidation tests/insert_test.go:105
Verified by Example_insertWithPresets tests/insert_test.go:184

Validation belongs in GraphJin config, not client code. Presets are useful for server-controlled fields such as owner_id, created_at, tenant IDs, or role-derived account IDs.

Updates

GraphQL
mutation {
  products(update: $data, where: { id: { eq: $id } }) {
    id
    name
  }
}
Verified by Example_update tests/update_test.go:61

Deletes

Deletes require a where clause. Do not expose unconstrained deletes.

GraphQL
mutation DeleteProduct($id: ID!) {
  products(delete: true, where: { id: { eq: $id } }) {
    id
  }
}
Verified by TestMultiAliasDelete tests/update_test.go:422

Read-only and production controls

Mutations run through the same role, source, and production policy gates as queries:

  • read-only databases or sources reject writes,
  • table-level permissions can block insert/update/upsert/delete separately,
  • production mode should use saved operations,
  • source-mode capabilities should come from core/sourcecap,
  • and MCP mutation access should be explicit.

Verified by TestReadOnlyDB_WithRolesAndTables tests/readonly_test.go:102
Verified by TestSourceModeHTTPRuntimeDenialEventsAreRedacted serv/source_mode_http_test.go:113

Dialect mutation strategies

The compiler lowers writes differently by dialect. PostgreSQL can use CTE-heavy nested mutation plans; MySQL, MariaDB, SQLite, SQL Server, Oracle, Snowflake, and other backends use dialect-specific linear or fallback strategies where needed. Shared mutation changes should be validated against relevant dialect scripts.

Docs