DBIx-Class-ResultDDL
view release on metacpan or search on metacpan
lib/DBIx/Class/ResultDDL/SchemaLoaderMixin.pm view on Meta::CPAN
warn "Unable to use ResultDDL sugar '$stmt'\n "
.deparse({ %col_info, %$out })." ne ".deparse($orig_col_info)."\n";
$stmt= join(', ',
map &_deparse_hashkey.' => '.deparse($orig_col_info->{$_}),
sort keys %$orig_col_info
);
}
return $stmt;
}
sub generate_relationship_sugar {
my ($self, $class, $method, $relname, $foreignclass, $colmap, $options)= @_;
#use DDP; &p(['before', @_[1..$#_]]);
my $expr= '';
# The $foreignclass $colmap arguments can be combined into a simpler
# hashref of { local_col => 'ForeignClass.colname' } as long as some expectations hold:
my ($parent_ns)= ($class =~ /^(.*?::)([^:]+)$/);
if (defined $parent_ns and !ref $foreignclass and (!ref $colmap || ref $colmap eq 'HASH')) {
# Can we use a shortened class name for the foreign table?
if ($foreignclass =~ /^(.*?::)([^:]+)$/ and $1 eq $parent_ns) {
$foreignclass= $2;
}
my %newmap= ref $colmap eq 'HASH'? (%$colmap) : ($colmap => $colmap);
# Just in case SchemaLoader prefixed them with 'self.' or 'foreign.'...
s/^self[.]// for values %newmap;
%newmap= reverse %newmap;
s/^foreign[.]// for values %newmap;
# Apply the foreign class name to the first column in the map
my ($first_key)= sort keys %newmap;
$newmap{$first_key}= $foreignclass . '.' . $newmap{$first_key};
$expr .= deparse(\%newmap);
} else {
$expr .= deparse($foreignclass, $colmap);
}
if ($options && keys %$options) {
$expr .= ', ' . $self->generate_relationship_attr_sugar($options);
}
# Test the syntax for equality to the original
my $checkpkg= $self->_get_class_check_namespace($class);
my @out;
eval "package $checkpkg; \@out= DBIx::Class::ResultDDL::expand_relationship_params(\$class, \$method, \$relname, $expr);";
@out or croak "Error verifying generated ResultDDL for $class $method $relname: $@";
#use DDP; &p(['after', @out, $expr]);
return $method . ' ' . deparse_hashkey($relname) . ' => ' . $expr . ';';
}
sub generate_relationship_attr_sugar {
my ($self, $orig_options)= @_;
my %options= %$orig_options;
my @expr;
if (defined $options{on_update} && defined $options{on_delete}
&& $options{on_update} eq $options{on_delete}
) {
my $val= delete $options{on_update};
delete $options{on_delete};
push @expr, $val eq 'CASCADE'? 'ddl_cascade'
: $val eq 'RESTRICT'? 'ddl_cascade(0)'
: 'ddl_cascade('.deparse($val).')'
}
if (defined $options{cascade_copy} && defined $options{cascade_delete}
&& $options{cascade_copy} eq $options{cascade_delete}
) {
my $val= delete $options{cascade_copy};
delete $options{cascade_delete};
push @expr, $val eq '1'? 'dbic_cascade'
: 'dbic_cascade('.deparse($val).')'
}
push @expr, substr(deparse(\%options),2,-2) if keys %options;
return join ', ', @expr
}
my %rel_methods= map +($_ => 1), qw( belongs_to might_have has_one has_many );
sub _dbic_stmt {
my ($self, $class, $method)= splice(@_, 0, 3);
# The first time we generate anything for each class, inject the 'use' line.
$self->_raw_stmt($class, $self->generate_resultddl_import_line($class))
unless $self->{_ResultDDL_SchemaLoader}{$class}{use_line}++;
if ($method eq 'table') {
$self->_raw_stmt($class, q|table |.deparse(@_).';');
}
elsif ($method eq 'add_columns') {
my @col_defs;
while (@_) {
my ($col_name, $col_info)= splice(@_, 0, 2);
push @col_defs, [
deparse_hashkey($col_name),
$self->generate_column_info_sugar($class, $col_name, $col_info)
];
}
# align the definitions, but round up to help avoid unnecessary diffs
# when new columns get added.
my $widest= max map length($_->[0]), @col_defs;
$widest= ($widest + 3) & ~3;
$self->_raw_stmt($class, sprintf("col %-*s => %s;", $widest, @$_))
for @col_defs;
}
elsif ($method eq 'set_primary_key') {
$self->_raw_stmt($class, q|primary_key |.deparse(@_).";");
}
elsif ($rel_methods{$method} && @_ == 4) {
# Add a linebreak before the relationships, for readability.
$self->_raw_stmt($class, "\n")
unless $self->{_ResultDDL_SchemaLoader}{$class}{relation_linebreak}++;
$self->_raw_stmt($class, $self->generate_relationship_sugar($class, $method, @_));
}
else {
$self->next::method($class, $method, @_);
}
return;
}
my %data_type_sugar= (
(map {
my $type= $_;
$type => sub { my ($col_info)= @_;
if ($col_info->{size} && $col_info->{size} =~ /^[0-9]+$/) {
return "$type(".delete($col_info->{size})."),";
} elsif ($col_info->{size} && ref $col_info->{size} eq 'ARRAY'
&& ($#{$col_info->{size}} == 0 || $#{$col_info->{size}} == 1)
&& (all { /^[0-9]+$/ } @{$col_info->{size}})
) {
return "$type(".join(',', @{delete($col_info->{size})})."),";
} else {
return $type;
}
}
( run in 0.592 second using v1.01-cache-2.11-cpan-5a3173703d6 )