whereSamePrimaryKey method

void whereSamePrimaryKey(
  1. Insertable<D> d
)

Applies a where statement so that the row with the same primary key as d will be matched.

Note that, as far as primary key equality is concerned, NULL values are considered distinct from all values (including other NULLs). This matches sqlite3's behavior of not counting duplicate NULLs as a uniqueness constraint violation for primary keys, but makes it impossible to find other rows with whereSamePrimaryKey if nullable primary keys are used.

Implementation

void whereSamePrimaryKey(Insertable<D> d) {
  final source = _sourceTable;
  assert(
      source.$primaryKey.isNotEmpty,
      'When using Query.whereSamePrimaryKey, which is also called from '
      'DeleteStatement.delete and UpdateStatement.replace, the affected table'
      'must have a primary key. You can either specify a primary implicitly '
      'by making an integer() column autoIncrement(), or by explictly '
      'overriding the primaryKey getter in your table class. You\'ll also '
      'have to re-run the code generation step.\n'
      'Alternatively, if you\'re using DeleteStatement.delete or '
      'UpdateStatement.replace, consider using DeleteStatement.go or '
      'UpdateStatement.write respectively. In that case, you need to use a '
      'custom where statement.');

  final primaryKeyColumns = Map.fromEntries(source.$primaryKey.map((column) {
    return MapEntry(column.$name, column);
  }));

  final updatedFields = d.toColumns(false);
  // Construct a map of [GeneratedColumn] to [Expression] where each column is
  // a primary key and the associated value was extracted from d.
  final primaryKeyValues = Map.fromEntries(updatedFields.entries
          .where((entry) => primaryKeyColumns.containsKey(entry.key)))
      .map((columnName, value) {
    return MapEntry(primaryKeyColumns[columnName]!, value);
  });

  assert(
    primaryKeyValues.values
        .every((value) => value is! Variable || value.value != null),
    'Tried to find a row with a matching primary key that has a null value, '
    'which is not supported. In sqlite3, `NULL` values in a primary key are '
    'considered distinct from all other values (including other `NULL`s), so '
    "drift can't find a matching row for this query. \n"
    'For details, see https://github.com/simolus3/drift/issues/1956#issuecomment-1200502026',
  );

  Expression<bool>? predicate;
  for (final entry in primaryKeyValues.entries) {
    final comparison =
        _Comparison(entry.key, _ComparisonOperator.equal, entry.value);

    if (predicate == null) {
      predicate = comparison;
    } else {
      predicate = predicate & comparison;
    }
  }

  whereExpr = Where(predicate!);
}