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 )