replace method
Replaces the old version of entity
that is stored in the database with
the fields of the entity
provided here. This implicitly applies a
where clause to rows with the same primary key as entity
, so that only
the row representing outdated data will be replaced.
If entity
has absent values (set to null on the DataClass or
explicitly to absent on the UpdateCompanion), and a default value for
the field exists, that default value will be used. Otherwise, the field
will be reset to null. This behavior is different to write, which simply
ignores such fields without changing them in the database.
When dontExecute
is true (defaults to false), the query will NOT be
run, but all the validations are still in place. This is mainly used
internally by drift.
Returns true if a row was affected by this operation.
See also:
- write, which doesn't apply a where statement itself and ignores null values in the entity.
- InsertStatement.insert with the
orReplace
parameter, which behaves similar to this method but creates a new row if none exists.
Implementation
Future<bool> replace(Insertable<D> entity, {bool dontExecute = false}) async {
// We don't turn nulls to absent values here (as opposed to a regular
// update, where only non-null fields will be written).
final columns = entity.toColumns(false);
_sourceTable
.validateIntegrity(entity, isInserting: true)
.throwIfInvalid(entity);
assert(
whereExpr == null,
'When using replace on an update statement, you may not use where(...)'
'as well. The where clause will be determined automatically');
whereSamePrimaryKey(entity);
// copying to work around type issues - Map<String, Variable> extends
// Map<String, Expression> but crashes when adding anything that is not
// a Variable.
_updatedFields = columns is Map<String, Variable>
? Map<String, Expression>.of(columns)
: columns;
final primaryKeys = _sourceTable.$primaryKey.map((c) => c.$name);
// entityToSql doesn't include absent values, so we might have to apply the
// default value here
for (final column in table.$columns) {
// if a default value exists and no value is set, apply the default
if (column.defaultValue != null &&
!_updatedFields.containsKey(column.$name)) {
_updatedFields[column.$name] = column.defaultValue!;
}
}
// Don't update the primary key
_updatedFields.removeWhere((key, _) => primaryKeys.contains(key));
if (dontExecute) return false;
final updatedRows = await _performQuery();
return updatedRows != 0;
}