NAME
DBIO::MySQL::Diff::PrimaryKey - Diff operations for MySQL/MariaDB primary keys
VERSION
version 0.900004
DESCRIPTION
Represents the primary key of a table that is in both models: ALTER TABLE ... ADD PRIMARY KEY for a table that has none (action add), ALTER TABLE ... DROP PRIMARY KEY, ADD PRIMARY KEY for a table whose key is composed differently (action replace, with old_columns), and ALTER TABLE ... DROP PRIMARY KEY for a table whose target has no key at all (action drop, a destructive operation: the summary names it and the columns the key had). The key of a table the diff creates is written into its CREATE TABLE by DBIO::MySQL::Diff::Table, and that of a table the diff drops goes with it. The PRIMARY index is no index of DBIO::MySQL::Diff::Index, and is_pk is no field of the column comparison, so the key is compared and written here.
The key is the list of the columns whose is_pk is true, in the order of pk_position, the position in the key (the introspection reads it from seq_in_index, target_from_compiled from the order of the primary key of the schema): the same columns in another order are another key, and the server indexes them differently. A model without pk_position is read in the order of the table. A key whose columns all go with the diff is dropped by the server with the last of them, and no statement is written for it; of a key that loses only some of its columns the rest is the key the server holds when this statement runs.
The two statements of a replace are one ALTER TABLE. Measured on MySQL 8.0 and MariaDB 11.8: an AUTO_INCREMENT column has to be a key of the table at every moment, and a DROP PRIMARY KEY of its own is refused (1075) where the same drop together with the new key is taken -- as long as the AUTO_INCREMENT column is the first column of the new key. An AUTO_INCREMENT column that leaves the key, or is not the first column of the new one, is no key of the table at that moment and the statement is refused (1075) -- unless another index over it, starting with it, exists: the UNIQUE index the target has over that column is created before the key (DBIO::MySQL::Diff). A column whose target has no such index is no valid schema (a table can have an AUTO_INCREMENT column only as a key), which the deploy refuses when it builds the target. The columns of a new key that are nullable become NOT NULL by the statement itself (a column holding NULL, or rows that repeat, make the server refuse it, as they should). The same goes for a column that is new: an AUTO_INCREMENT column of the key that the diff adds is part of that one statement (with_columns, the ADD COLUMN operations it takes over from DBIO::MySQL::Diff::Column), the server refusing it without its key.
The key of the source is dropped when the target has none. An AUTO_INCREMENT column of that key has to be released first, the server refusing the plain drop (1075); DBIO::MySQL::Diff writes the MODIFY without the attribute before the drop (the column diff has it anyway where the target column does not keep the attribute) and, where the target keeps it on a column with a key of another kind, gives it back after that key exists.
The server refuses to drop, or to change the start of, a primary key that a foreign key of the table or a foreign key into the table needs as its index (MySQL 1553, MariaDB errno 150). DBIO::MySQL::Diff drops those foreign keys before the statement and adds them after it, unchanged, and refuses a foreign key the target declares over columns that the target has no key over any more (DBIO::Exception, naming table and constraint) instead of dropping it unseen.
DBIO::MySQL::Diff puts the operation after the column changes, where the columns of the key exist, and before the indexes that are created and the foreign keys that are added. A column that gains AUTO_INCREMENT and is in the key is the one exception: its MODIFY COLUMN needs the key, so the key comes first.
METHODS
primary_key_columns
my @names = primary_key_columns($columns);
The names of the columns of the primary key in the order of the key, from the columns list of one table of a model.
diff
my @ops = DBIO::MySQL::Diff::PrimaryKey->diff(
$source_columns, $target_columns, $source_tables, $target_tables);
The columns and tables sections of the two models. Only a table that is in both models is looked at.
as_sql
The ALTER TABLE statement, every name quoted with "quote_ident" in DBIO::MySQL::Identifier.
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.