createContext method

GenerationContext createContext(
  1. Insertable<D> entry,
  2. InsertMode mode,
  3. {UpsertClause<T, D>? onConflict,
  4. bool returning = false}
)

Creates a GenerationContext which contains the sql necessary to run an insert statement fro the entry with the mode.

This method is used internally by drift. Consider using insert instead.

Implementation

GenerationContext createContext(Insertable<D> entry, InsertMode mode,
    {UpsertClause<T, D>? onConflict, bool returning = false}) {
  _validateIntegrity(entry);

  final rawValues = entry.toColumns(true);

  // apply default values for columns that have one
  final map = <String, Expression>{};
  for (final column in table.$columns) {
    final columnName = column.$name;

    if (rawValues.containsKey(columnName)) {
      final value = rawValues[columnName]!;
      map[columnName] = value;
    } else {
      if (column.clientDefault != null) {
        map[columnName] = column._evaluateClientDefault();
      }
    }

    // column not set, and doesn't have a client default. So just don't
    // include this column
  }

  // The rowid is not included in the list of columns since it doesn't show
  // up in selects, but we should also add that value to the map for inserts.
  if (rawValues.containsKey('rowid')) {
    map['rowid'] = rawValues['rowid']!;
  }

  final ctx = GenerationContext.fromDb(database);
  mode.writeInto(ctx);

  ctx.buffer
    ..write(' INTO ')
    ..write(ctx.identifier(table.aliasedName))
    ..write(' ');

  if (map.isEmpty) {
    ctx.buffer.write('DEFAULT VALUES');
  } else {
    writeInsertable(ctx, map);
  }

  _writeOnConflict(ctx, mode, entry, onConflict);

  if (returning) {
    ctx.buffer.write(' RETURNING *');
  } else if (ctx.dialect == SqlDialect.postgres) {
    if (table.$primaryKey.length == 1) {
      final id = table.$primaryKey.firstOrNull;
      if (id != null && id.type == DriftSqlType.int) {
        ctx.buffer.write(' RETURNING ${id.name}');
      }
    }
  }

  return ctx;
}