atomicWrite method
Executes transaction-safe DML statements as one atomic write batch.
Every statement must declare SqlStatementKind.write. An empty batch is valid and returns an empty result without starting a transaction.
Results preserve input order. Either every statement commits or none do. Transaction control, DDL that implicitly commits, and row-returning statements are outside this contract.
Implementation
@override
Future<List<SqlWriteResult>> atomicWrite(List<BoundSql> statements) async {
final copiedStatements = List<BoundSql>.unmodifiable(statements);
_ensureOpen();
_requireAtomicWrites(copiedStatements);
if (copiedStatements.isEmpty) return const <SqlWriteResult>[];
final JSArray<_D1PreparedStatement> prepared;
try {
prepared = <_D1PreparedStatement>[
for (final statement in copiedStatements) _prepare(statement),
].toJS;
} on Object catch (error) {
_throwD1(error);
}
final JSAny? results;
try {
results = await _database.batch(prepared).toDart;
} on Object catch (error) {
_throwD1(error);
}
if (results == null || !results.isA<JSArray<JSAny?>>()) {
throw const SqlException(
SqlErrorCode.invalidRow,
'D1 returned an invalid batch result.',
);
}
final values = (results as JSArray<JSAny?>).toDart;
if (values.length != copiedStatements.length) {
throw const SqlException(
SqlErrorCode.invalidRow,
'D1 returned the wrong number of batch results.',
);
}
return <SqlWriteResult>[
for (final result in values) _readWriteResult(result),
];
}