returning<R> method

SqlRead<R> returning<R>(
  1. SqlProjection<R> projection
)

Adds a row-returning projection to this mutation.

The result type exposes only row-returning terminals, so RETURNING statements cannot accidentally use SqlExecutor.execute. MySQL rejects this operation before any database call.

Implementation

SqlRead<R> returning<R>(SqlProjection<R> projection) {
  final dialect = statement.dialect!;
  if (!supportsSqlReturning(dialect)) {
    throw const SqlException(
      SqlErrorCode.unsupported,
      'MySQL does not support SQL RETURNING in this query layer.',
    );
  }
  for (final selection in projection.columns) {
    final column = selection._source;
    if (!identical(column.table, _table)) {
      throw ArgumentError(
        'Returning column "${column.name}" does not belong to '
        'table "${_table.name}".',
      );
    }
  }

  final fragments = List<String>.of(statement.fragments);
  final suffix = StringBuffer(' RETURNING ');
  for (final (index, selection) in projection.columns.indexed) {
    if (index != 0) suffix.write(', ');
    final column = selection._source;
    suffix.write(dialect.quoteIdentifier(column.name));
    final resultName = selection._resultColumn.name;
    if (resultName != column.name) {
      suffix
        ..write(' AS ')
        ..write(dialect.quoteIdentifier(resultName));
    }
  }
  fragments[fragments.length - 1] = '${fragments.last}${suffix.toString()}';
  return SqlRead<R>._(
    BoundSql.parts(
      fragments,
      statement.values,
      kind: SqlStatementKind.rowReturning,
      dialect: dialect,
    ),
    projection.decode,
  );
}