NAME

DBIO::MySQL::Diff::Column - Diff operations for MySQL/MariaDB columns

VERSION

version 0.900004

DESCRIPTION

Represents a column-level diff operation in MySQL/MariaDB. Unlike SQLite, MySQL has full ALTER TABLE support so all of ADD COLUMN, DROP COLUMN, and MODIFY COLUMN are emitted directly.

Brand-new tables get their columns inline via DBIO::MySQL::Diff::Table -- this module only sees columns of tables that exist in both source and target.

ATTRIBUTES

lossy_pairs

my %pairs = %DBIO::MySQL::Diff::Column::LOSSLESS_PAIRS;

The changes of data_type that MySQL and MariaDB carry out without loss, as the old->new keys "column_change_lossy" in DBIO::Diff::Compare reads: the integer types to a wider one (tinyint < smallint < mediumint < int < bigint), the text types and the blob types to a larger one, char to varchar, char and varchar to text, mediumtext and longtext (tinytext holds 255 bytes, fewer than a varchar(255)), binary to varbinary, varbinary to the blobs from blob up, and date to datetime. Every other pair of types is lossy, in doubt it is: float to double alters the decimal reading of a value, datetime to timestamp narrows the range, a number to a string rewrites it.

METHODS

diff

my @ops = DBIO::MySQL::Diff::Column->diff(
    $source_cols, $target_cols,
    $source_tables, $target_tables,
);

Compares column lists for tables that exist in both source and target. Detects added columns, dropped columns, and modified columns (data type, NOT NULL, default value or ON UPDATE changes). Returns a list of DBIO::MySQL::Diff::Column objects. ON UPDATE (on_update in the model) is compared when the target carries the key, as the introspection does for every column, and MODIFY COLUMN, ADD COLUMN and the CREATE TABLE of DBIO::MySQL::Diff::Table write it; a column whose target has none loses it, and a target from target_from_compiled, which has no such key, leaves it alone. A column that gains or loses AUTO_INCREMENT is modified too, and a MODIFY COLUMN of a column that is AUTO_INCREMENT in the target keeps the attribute. A column that is AUTO_INCREMENT without being the primary key has to have a key; the statement that takes the attribute from it stands before the DROP INDEX of that key, see DBIO::MySQL::Diff. The columns a table gains are added in the order the target declares them, not in the order of their names.

The MySQL column shape carries extras beyond the canonical model (column_type, character_set, collation, numeric_precision, numeric_scale, datetime_precision, values, comment) so we use "changed_fields" in DBIO::Diff::Compare with a MySQL-specific field spec instead of the canonical changed_column_fields.

A column with a character set or collation of its own, off the default of its table, has them written by MODIFY COLUMN and ADD COLUMN ("collation_sql"); one on the default is written without.

lossy

True for a modify that can alter or lose stored values, so that "apply" in DBIO::Deploy::Base runs it only with allow_destructive. The answer is "column_change_lossy" in DBIO::Diff::Compare over the types and sizes of the two columns, with the pairs of "lossy_pairs", and four things the generic comparison does not see:

  • unsigned gained or lost -- negative values go, or large ones do not fit;

  • another character_set -- text of one may not be representable in the other;

  • an enum or set whose values are not the old ones with more behind them;

  • a type without a size of its own (float, double, json, ...) whose column_type is another string.

A change of NOT NULL, the default, the comment, ON UPDATE, the collation within one character set and AUTO_INCREMENT keeps every value and is not lossy (NOT NULL over a NULL is refused by "_refuse_unfillable" in DBIO::MySQL::Deploy). The integer display width (int(11)) is no size. Other actions are not lossy.

collation_sql

my $sql = DBIO::MySQL::Diff::Column::collation_sql($column_info, $table_collation);

The CHARACTER SET and COLLATE of a column, with a leading blank, where they differ from the default of its table, and the empty string where they do not. A column on the default is written without, as the server gives it the default of the table; one off it needs them in every MODIFY COLUMN, ADD COLUMN and CREATE TABLE, or the statement resets it and the next diff finds it again. Compared as the introspection reports them: case aside, the character set of the table taken from the prefix of its collation. A table whose default is not known (a target from target_from_compiled) gets what the column says; a column that says nothing gets nothing.

as_sql

The ALTER TABLE statement. The names of the table and the column are quoted with "quote_ident" in DBIO::MySQL::Identifier.

add_clause

my $clause = $op->add_clause;        # ADD COLUMN `c` int(11) NOT NULL
my $clause = $op->add_clause(1);     # ... NOT NULL AUTO_INCREMENT

The ADD COLUMN clause of an add operation, without the ALTER TABLE. AUTO_INCREMENT is written only when asked for: the server refuses it on a column that is no key, so DBIO::MySQL::Diff::PrimaryKey takes the clause of a column that is its key into the statement that adds the key.

summary

AUTHOR

DBIO & DBIx::Class Authors

COPYRIGHT AND LICENSE

Copyright (C) 2026 DBIO Authors Portions Copyright (C) 2005-2025 DBIx::Class Authors Based on DBIx::Class, heavily modified.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.