executeMutationWithRelations method

Future<Map<String, dynamic>?> executeMutationWithRelations(
  1. JsonQuery query
)

Execute a mutation with potential relation operations (connect/disconnect).

This method handles CREATE and UPDATE queries that include connect or disconnect operations for many-to-many relations. It executes the main mutation first, then executes all relation mutations in sequence.

If the main mutation succeeds but a relation mutation fails, the main record will already be created/updated. Consider using executeMutationWithRelationsAtomic for atomic operations.

Example:

final result = await executor.executeMutationWithRelations(
  JsonQueryBuilder()
      .model('SlotOfAppointment')
      .action(QueryAction.create)
      .data({
        'id': 'slot-123',
        'startsAt': DateTime.now(),
        'users': {
          'connect': [{'id': 'user-1'}],
        },
      })
      .build(),
);

Implementation

Future<Map<String, dynamic>?> executeMutationWithRelations(
  JsonQuery query,
) async {
  // Compile with relation support
  final compiled = compiler.compileWithRelations(query);

  // Execute main mutation
  final result = await adapter.queryRaw(compiled.mainQuery);
  final mainRow =
      result.rows.isNotEmpty ? resultSetToMaps(result).first : null;

  // Rebuild relation mutations from the RETURNING row so DB-generated parent
  // ids (e.g. @default(uuid())) are used, not the compile-time (null) id.
  final relationMutations =
      compiler.buildRelationMutationsFromResult(query, mainRow);

  if (relationMutations.isNotEmpty) {
    for (final relationQuery in relationMutations) {
      try {
        await adapter.executeRaw(relationQuery);
      } catch (e, s) {
        // Log the error but continue with other relation mutations
        // This is the non-atomic version - errors are logged but don't stop execution
        // Use executeMutationWithRelationsAtomic() if you need all-or-nothing behavior
        logger?.onQueryError(QueryErrorEvent(
          sql: relationQuery.sql,
          parameters: relationQuery.args,
          model: query.modelName,
          operation: 'relationMutation',
          duration: Duration.zero,
          error: e,
          stackTrace: s,
        ));
        // Don't rethrow - continue with other mutations (non-atomic behavior)
      }
    }
  }

  // Return the created/updated record
  return mainRow;
}