DBIO

 view release on metacpan or  search on metacpan

lib/DBIO/Diff/Op.pm  view on Meta::CPAN

      next if exists $target->{$table};
      my $src = _members_by_key($source->{$table}, $index_by);
      for my $name (sort keys %$src) {
        my $old = $src->{$name};
        next if $skip && $skip->($old);
        push @ops, $opt{on_gone}->($table, $name, $old) if $opt{on_gone};
      }
    }
  }

  return @ops;
}


sub should_emit_if_exists {
  my ($storage) = @_;
  return 0 unless $storage;
  return 0 unless ref($storage) && $storage->can('_use_if_exists');
  return $storage->_use_if_exists ? 1 : 0;
}

1;

__END__

=pod

=encoding UTF-8

=head1 NAME

DBIO::Diff::Op - Base class for DBIO driver diff operation objects

=head1 VERSION

version 0.900002

=head1 DESCRIPTION

Base class for the per-engine diff operation objects (the C<Diff::Table>,
C<Diff::Column>, C<Diff::Index>, C<Diff::ForeignKey> classes each driver ships).
Those classes were byte-for-byte identical in their C<new>/accessor boilerplate
and 90-95% identical in their C<diff()> create/drop/alter walks across every
driver; only C<as_sql> (quoting, C<ENGINE=>, schema qualification, type
rendering) is genuinely engine-specific.

This base hosts the shared parts:

=over 4

=item * L</new> and the C<action> accessor, plus L</mk_diff_accessors> to
declare the rest without hand-rolling C<< sub foo { $_[0]->{foo} } >> lines.

=item * L</diff_toplevel> -- the create/drop walk for a flat keyed collection
(tables: a name exists only in the target -> create, only in the source ->
drop; no in-place change).

=item * L</diff_nested> -- the create/change/drop walk for members nested under
tables (columns, indexes, foreign keys), parameterized by a per-engine
"did this member change?" predicate (e.g. the C<is_same_*> functions from
L<DBIO::Diff::Compare>) and per-engine op-construction callbacks.

=item * L</summary_prefix> -- the C<+>/C<->/C<~> action glyph used in summaries.

=item * L</should_emit_if_exists> -- the F12 helper a per-driver C<as_sql>
calls to decide whether to emit C<IF [NOT] EXISTS> guards.

=back

Subclasses keep C<as_sql> (the real engine seam) and a thin C<summary>, and
call these helpers from their own C<diff> class method. Drivers whose diff is
orchestrated differently (e.g. PostgreSQL's registry-based dispatch, or its
global definition-string index comparison) are free to ignore the walk helpers
and use only L</new>/L</mk_diff_accessors>/L</summary_prefix>/L</should_emit_if_exists>.

=head1 METHODS

=head2 new

    my $op = $class->new(action => 'create', table_name => 'foo', ...);

Blesses the argument hash into the operation class.

=head2 mk_diff_accessors

    __PACKAGE__->mk_diff_accessors(qw/table_name column_name old_info new_info/);

Declares simple hash-slot accessors for the operation class. C<action> is
already provided by this base. This is a thin alias over
C<Class::Accessor::Grouped>'s C<simple> group.

=head2 summary_prefix

    my $glyph = $op->summary_prefix;            # by action, sensible defaults
    my $glyph = $op->summary_prefix(add => '*'); # override per action

Returns the one-character glyph for this op's C<action>: C<+> for
C<create>/C<add>, C<-> for C<drop>, C<~> for C<alter>/C<modify>/C<change>.
Pass an C<< action => glyph >> map to override. Unknown actions default to C<~>.

=head2 diff_toplevel

    my @ops = $class->diff_toplevel($source, $target,
      create => sub { my ($name) = @_; $class->new(action => 'create', ...) },
      drop   => sub { my ($name) = @_; $class->new(action => 'drop',   ...) },
    );

The create/drop walk for a flat collection keyed by name (the table-level
diff). C<$source> and C<$target> are hashrefs C<< { $name => $info } >>. For
each name present only in C<$target> the C<create> callback is invoked; for
each name present only in C<$source> the C<drop> callback is invoked. Names
present in both are left untouched (table identity has no in-place change here;
column/index/fk changes are handled by L</diff_nested>). Names are walked in
sorted order. Each callback may return zero or more ops; all are collected.

=head2 diff_nested

    my @ops = $class->diff_nested($source, $target,
      index_by      => 'column_name',     # omit if members are already a hash
      scope         => 'both',            # or 'all'
      source_tables => $src_model->{tables},



( run in 1.433 second using v1.01-cache-2.11-cpan-6aa56a78535 )