DBIO-MySQL

 view release on metacpan or  search on metacpan

t/40-diff.t  view on Meta::CPAN

  my @ops = DBIO::MySQL::Diff::Index->diff(
    { t => { gone_idx => {
      index_name => 'gone_idx', columns => ['x'], origin => 'c',
    }}},
    {},
  );
  is($ops[0]->as_sql, 'DROP INDEX `gone_idx` ON `t`;', 'drop index SQL');
}

# --- Diff::Index: owning table dropped -> suppress standalone DROP INDEX (karr #23) ---
# When the table itself is being dropped in the same pass (present in source
# tables, absent from target tables), DROP TABLE already removes the table's
# own indexes, so no standalone DROP INDEX must be emitted for them.
{
  my @ops = DBIO::MySQL::Diff::Index->diff(
    { leftover => { idx_leftover_x => {
      index_name => 'idx_leftover_x', columns => ['x'], origin => 'c',
    }}},
    {},
    { leftover => { table_name => 'leftover' } },   # source tables: leftover exists
    {},                                             # target tables: gone -> dropped
  );
  is(scalar @ops, 0, 'no standalone DROP INDEX when owning table is dropped (DROP TABLE covers it)');
}

# --- Diff::Index: over-suppression guard (karr #23) ---
# A table that STAYS but loses one of its indexes must still get a standalone
# DROP INDEX -- the suppression only applies to indexes of dropped tables.
{
  my @ops = DBIO::MySQL::Diff::Index->diff(
    { users => { idx_users_email => {
      index_name => 'idx_users_email', columns => ['email'], origin => 'c',
    }}},
    {},
    { users => { table_name => 'users' } },   # source tables: users exists
    { users => { table_name => 'users' } },   # target tables: users still exists
  );
  is(scalar @ops, 1, 'index drop still emitted when the table itself survives');
  is($ops[0]->action, 'drop', 'surviving-table index drop is a drop op');
  is($ops[0]->as_sql, 'DROP INDEX `idx_users_email` ON `users`;',
    'surviving-table index still dropped standalone');
}

# --- Diff::ForeignKey add ---
{
  my @ops = DBIO::MySQL::Diff::ForeignKey->diff(
    { t => [] },
    { t => [{
      constraint_name => 'fk_t_other',
      from_columns => ['other_id'],
      to_table     => 'other',
      to_columns   => ['id'],
      on_update    => 'NO ACTION',
      on_delete    => 'CASCADE',
    }]},
    { t => {} }, { t => {} },
  );
  is(scalar @ops, 1, 'one fk add');
  my $sql = $ops[0]->as_sql;
  like($sql, qr/ADD CONSTRAINT `fk_t_other` FOREIGN KEY \(`other_id`\) REFERENCES `other`\(`id`\)/, 'add fk');
  like($sql, qr/ON DELETE CASCADE/, 'on delete cascade');
  unlike($sql, qr/ON UPDATE/, 'on update NO ACTION omitted');
}

# --- Diff::ForeignKey drop ---
{
  my @ops = DBIO::MySQL::Diff::ForeignKey->diff(
    { t => [{
      constraint_name => 'fk_old', from_columns => ['x'],
      to_table => 'other', to_columns => ['id'],
    }]},
    { t => [] },
    { t => {} }, { t => {} },
  );
  is($ops[0]->action, 'drop', 'drop fk');
  is($ops[0]->as_sql, 'ALTER TABLE `t` DROP FOREIGN KEY `fk_old`;', 'drop fk SQL');
}

# --- Top-level orchestrator ---
{
  my $diff = DBIO::MySQL::Diff->new(
    source => { tables => {}, columns => {}, indexes => {}, foreign_keys => {} },
    target => {
      tables       => { t => { table_name => 't', engine => 'InnoDB' } },
      columns      => { t => [ { column_name => 'id', column_type => 'int(11)', is_pk => 1 } ] },
      indexes      => {},
      foreign_keys => {},
    },
  );
  ok($diff->has_changes, 'has changes');
  like($diff->as_sql, qr/CREATE TABLE `t`/, 'orchestrator emits CREATE TABLE');
  like($diff->summary, qr/\+ table: t/, 'summary line');
}

# --- Identical models = no changes ---
{
  my $model = {
    tables       => { t => { table_name => 't' } },
    columns      => { t => [ { column_name => 'id', column_type => 'int' } ] },
    indexes      => {},
    foreign_keys => {},
  };
  my $diff = DBIO::MySQL::Diff->new(source => $model, target => $model);
  ok(!$diff->has_changes, 'identical = no changes');
}

done_testing;



( run in 1.928 second using v1.01-cache-2.11-cpan-e7c6538aa59 )