insert method

Future<int> insert(
  1. Insertable<D> entity,
  2. {InsertMode? mode,
  3. UpsertClause<T, D>? onConflict}
)

Inserts a row constructed from the fields in entity.

All fields in the entity that don't have a default value or auto-increment must be set and non-null. Otherwise, an InvalidDataException will be thrown.

By default, an exception will be thrown if another row with the same primary key already exists. This behavior can be overridden with mode, for instance by using InsertMode.replace or InsertMode.insertOrIgnore.

To apply a partial or custom update in case of a conflict, you can also use an upsert clause by using onConflict. For instance, you could increase a counter whenever a conflict occurs:

class Words extends Table {
  TextColumn get word => text()();
  IntColumn get occurrences => integer()();
}

Future<void> addWord(String word) async {
  await into(words).insert(
    WordsCompanion.insert(word: word, occurrences: 1),
    onConflict: DoUpdate((old) => WordsCompanion.custom(
      occurrences: old.occurrences + Constant(1),
    )),
  );
}

When calling addWord with a word not yet saved, the regular insert will write it with one occurrence. If it already exists however, the insert behaves like an update incrementing occurrences by one. Be aware that upsert clauses and onConflict are not available on older sqlite versions.

By default, the onConflict clause will only consider the table's primary key. If you have additional columns with uniqueness constraints, you have to manually add them to the clause's DoUpdate.target.

Returns the rowid of the inserted row. For tables with an auto-increment column, the rowid is the generated value of that column. The returned value can be inaccurate when onConflict is set and the insert behaved like an update.

If the table doesn't have a rowid, you can't rely on the return value. Still, the future will always complete with an error if the insert fails.

Implementation

Future<int> insert(
  Insertable<D> entity, {
  InsertMode? mode,
  UpsertClause<T, D>? onConflict,
}) async {
  final ctx = createContext(entity, mode ?? InsertMode.insert,
      onConflict: onConflict);

  return await database.withCurrentExecutor((e) async {
    final id = await e.runInsert(ctx.sql, ctx.boundVariables);
    database
        .notifyUpdates({TableUpdate.onTable(table, kind: UpdateKind.insert)});
    return id;
  });
}