changeColumnType method
Changes the type of the column name to type, with its length,
precision and scale, which are as for a Column: without a precision
or scale, a numeric is unbounded on PostgreSQL, so that its values are
kept, and numeric(17, 3) on MySQL and MariaDB.
The column has the constraints given after the change: it is nullable or
not as isNullable, has the default defaultValue, or none if it is
noDefault, and on MySQL and MariaDB is AUTO_INCREMENT or not as
autoIncrement. Those not given (null) are kept as they are; a default
that the new type cannot have, such as 'n/a' of an int, is removed
with noDefault. MySQL and MariaDB define the whole column
again, so the migration runner reads them from the database first; they
keep its NOT NULL, DEFAULT, AUTO_INCREMENT, ON UPDATE, UNSIGNED,
generation, INVISIBLE and COMMENT, its CHARACTER SET and COLLATE
for a type of text, and on MariaDB its CHECK, where the new type can
have them.
On PostgreSQL, using is the expression that converts the values when
there is no implicit cast, such as price::numeric from text.
Throws an ArgumentError if type has a precision and precision is
not positive, or has a scale and scale is negative or greater than the
precision.
Implementation
@override
void changeColumnType(
String name,
ColumnType type, {
int length = Column.defaultLength,
int? precision,
int? scale,
bool? isNullable,
Object? defaultValue,
bool? autoIncrement,
String? using,
}) {
// A serial type is not a type that a column can be changed to, but an
// integer with a default from a sequence, which a serial column keeps,
// and which compileSequences gives a column without one.
// With `autoIncrement: false`, a serial type is only its integer, as on
// MySQL and MariaDB, and so it is with `noDefault`, the default from its
// sequence being one, unless `autoIncrement: true` is given.
var integer = sql.serialIntegers[type];
var serial =
integer != null &&
autoIncrement != false &&
!identical(defaultValue, noDefault);
if (serial || autoIncrement == true) {
_sequences[_columnKey(name)] =
_sequenceTypes[integer ?? type] ?? 'bigint';
}
var column = changedColumn(
integer ?? type,
length: length,
precision: precision,
scale: scale,
);
// The column keeps its constraints, and gets those given. A new default,
// or noDefault, replaces the old one, which is dropped first, as it may
// not be cast to the new type.
if (defaultValue != null) {
_clause(
'ALTER COLUMN ${sql.quotePostgresIdentifier(name)} DROP DEFAULT',
[name],
);
}
_clause(
'ALTER COLUMN ${sql.quotePostgresIdentifier(name)} TYPE ${PostgresGenerator.columnType(column)}'
'${using == null ? '' : ' USING $using'}',
[name],
);
if (isNullable != null) {
_clause(
'ALTER COLUMN ${sql.quotePostgresIdentifier(name)} ${isNullable ? 'DROP' : 'SET'} NOT NULL',
[name],
);
}
if (defaultValue != null && !identical(defaultValue, noDefault)) {
_clause(
'ALTER COLUMN ${sql.quotePostgresIdentifier(name)} SET DEFAULT '
'${PostgresGenerator.compileDefault(defaultValue)}',
[name],
);
}
}