alterColumn method

void alterColumn(
  1. String tableName,
  2. String columnName,
  3. void modify(
    1. SchemaColumn targetColumn
    ), {
  4. String? unencodedInitialValue,
})

Validates and alters a column in a table in schema.

Alterations are made by setting properties of the column passed to modify. If the column's nullability changes from nullable to not nullable, all previously null values for that column are set to the value of unencodedInitialValue.

Example:

    database.alterColumn("table", "column", (c) {
      c.isIndexed = true;
      c.isNullable = false;
    }), unencodedInitialValue: "0");

Implementation

void alterColumn(
  String tableName,
  String columnName,
  void Function(SchemaColumn targetColumn) modify, {
  String? unencodedInitialValue,
}) {
  final table = schema.tableForName(tableName);
  if (table == null) {
    throw SchemaException("Table $tableName does not exist.");
  }

  final existingColumn = table[columnName];
  if (existingColumn == null) {
    throw SchemaException("Column $columnName does not exist.");
  }

  final newColumn = SchemaColumn.from(existingColumn);
  modify(newColumn);

  if (existingColumn.type != newColumn.type) {
    throw SchemaException(
      "May not change column type for '${existingColumn.name}' in '$tableName' (${existingColumn.typeString} -> ${newColumn.typeString})",
    );
  }

  if (existingColumn.autoincrement != newColumn.autoincrement) {
    throw SchemaException(
      "May not change column autoincrementing behavior for '${existingColumn.name}' in '$tableName'",
    );
  }

  if (existingColumn.isPrimaryKey != newColumn.isPrimaryKey) {
    throw SchemaException(
      "May not change column primary key status for '${existingColumn.name}' in '$tableName'",
    );
  }

  if (existingColumn.relatedTableName != newColumn.relatedTableName) {
    throw SchemaException(
      "May not change reference table for foreign key column '${existingColumn.name}' in '$tableName' (${existingColumn.relatedTableName} -> ${newColumn.relatedTableName})",
    );
  }

  if (existingColumn.relatedColumnName != newColumn.relatedColumnName) {
    throw SchemaException(
      "May not change reference column for foreign key column '${existingColumn.name}' in '$tableName' (${existingColumn.relatedColumnName} -> ${newColumn.relatedColumnName})",
    );
  }

  if (existingColumn.name != newColumn.name) {
    renameColumn(tableName, existingColumn.name, newColumn.name);
  }

  table.replaceColumn(existingColumn, newColumn);

  final innerCommands = <String>[];
  if (existingColumn.isIndexed != newColumn.isIndexed) {
    if (store != null) {
      if (newColumn.isIndexed!) {
        commands.addAll(store!.addIndexToColumn(table, newColumn));
      } else {
        commands.addAll(store!.deleteIndexFromColumn(table, newColumn));
      }
    } else {
      innerCommands.add("c.isIndexed = ${newColumn.isIndexed}");
    }
  }

  if (existingColumn.isUnique != newColumn.isUnique) {
    if (store != null) {
      commands.addAll(store!.alterColumnUniqueness(table, newColumn));
    } else {
      innerCommands.add('c.isUnique = ${newColumn.isUnique}');
    }
  }

  if (existingColumn.defaultValue != newColumn.defaultValue) {
    if (store != null) {
      commands.addAll(store!.alterColumnDefaultValue(table, newColumn));
    } else {
      final value = newColumn.defaultValue == null
          ? 'null'
          : '"${newColumn.defaultValue}"';
      innerCommands.add('c.defaultValue = $value');
    }
  }

  if (existingColumn.isNullable != newColumn.isNullable) {
    if (store != null) {
      commands.addAll(
        store!
            .alterColumnNullability(table, newColumn, unencodedInitialValue),
      );
    } else {
      innerCommands.add('c.isNullable = ${newColumn.isNullable}');
    }
  }

  if (existingColumn.deleteRule != newColumn.deleteRule) {
    if (store != null) {
      commands.addAll(store!.alterColumnDeleteRule(table, newColumn));
    } else {
      innerCommands.add('c.deleteRule = ${newColumn.deleteRule}');
    }
  }

  if (store == null && innerCommands.isNotEmpty) {
    commands.add(
      'database.alterColumn("$tableName", "$columnName", (c) {${innerCommands.join(";")};});',
    );
  }
}