__PACKAGE__->mk_group_accessors('simple' => qw/_ordered_columns
_columns _primaries _unique_constraints name resultset_attributes
schema from _relationships column_info_from_storage source_info
- source_name _indexes/);
+ source_name/);
__PACKAGE__->mk_group_accessors('component_class' => qw/resultset_class
result_class/);
$new->{_relationships} = { %{$new->{_relationships}||{}} };
$new->{name} ||= "!!NAME NOT SET!!";
$new->{_columns_info_loaded} ||= 0;
- $new->_indexes([]) unless $new->_indexes;
return $new;
}
will attempt to retrieve the name of the sequence from the database
automatically.
+=item auto_nextval
+
+Set this to a true value for a column whose value is retrieved
+automatically from an oracle sequence. If you do not use an oracle
+trigger to get the nextval, you have to set sequence as well.
+
=item extra
This is used by L<DBIx::Class::Schema/deploy> and L<SQL::Translator>
sub storage { shift->schema->storage; }
-=head2 add_index
-
-Add an index to the result source. This has no effect for DBIx::Class - it is
-just used for creating SQL with L<SQL::Translator>. Takes the same arguments
-as L<SQL::Translator::Schema::Table::add_index>.
-
-=cut
-
-sub add_index {
- my ($self, $idx) = @_;
-
- push @{ $self->_indexes }, $idx;
-}
-
-=head2 indexes
-
-Returns list of secondary (i.e. non unique) indexes created on this table.
-
-=cut
-
-sub indexes {
- return @{ shift->_indexes };
-}
-
=head2 add_relationship
$source->add_relationship('relname', 'related_source', $cond, $attrs);
my $otherrel_info = $othertable->relationship_info($otherrel);
my $back = $othertable->related_source($otherrel);
- next unless $back->name eq $self->name;
+ next unless $back->source_name eq $self->source_name;
my @othertestconds;
}
}
+=head2 pk_depends_on
+
+=over 4
+
+=item Arguments: $relname, $rel_data
+
+=back
+
+Determines whether a relation is dependent on an object from this source
+having already been inserted. Takes the name of the relationship and a
+hashref of columns of the related object.
+
+=cut
+
+sub pk_depends_on {
+ my ($self, $relname, $rel_data) = @_;
+ my $cond = $self->relationship_info($relname)->{cond};
+
+ return 0 unless ref($cond) eq 'HASH';
+
+ # map { foreign.foo => 'self.bar' } to { bar => 'foo' }
+
+ my $keyhash = { map { my $x = $_; $x =~ s/.*\.//; $x; } reverse %$cond };
+
+ # assume anything that references our PK probably is dependent on us
+ # rather than vice versa, unless the far side is (a) defined or (b)
+ # auto-increment
+
+ my $rel_source = $self->related_source($relname);
+
+ foreach my $p ($self->primary_columns) {
+ if (exists $keyhash->{$p}) {
+ unless (defined($rel_data->{$keyhash->{$p}})
+ || $rel_source->column_info($keyhash->{$p})
+ ->{is_auto_increment}) {
+ return 0;
+ }
+ }
+ }
+
+ return 1;
+}
+
=head2 resolve_condition
=over 4
=cut
+our $UNRESOLVABLE_CONDITION = \'1 = 0';
+
sub resolve_condition {
my ($self, $cond, $as, $for) = @_;
#warn %$cond;
$self->throw_exception("Invalid rel cond val ${v}");
if (ref $for) { # Object
#warn "$self $k $for $v";
- $ret{$k} = $for->get_column($v) if $for->has_column_loaded($v);
+ unless ($for->has_column_loaded($v)) {
+ if ($for->in_storage) {
+ $self->throw_exception("Column ${v} not loaded on ${for} trying to resolve relationship");
+ }
+ return $UNRESOLVABLE_CONDITION;
+ }
+ $ret{$k} = $for->get_column($v);
+ #$ret{$k} = $for->get_column($v) if $for->has_column_loaded($v);
#warn %ret;
} elsif (!defined $for) { # undef, i.e. "no object"
$ret{$k} = undef;
$self->throw_exception(
"Can't prefetch has_many ${pre} (join cond too complex)")
unless ref($rel_info->{cond}) eq 'HASH';
+ my $dots = @{[$as_prefix =~ m/\./g]} + 1; # +1 to match the ".${as_prefix}"
+ if (my ($fail) = grep { @{[$_ =~ m/\./g]} == $dots }
+ keys %{$collapse}) {
+ my ($last) = ($fail =~ /([^\.]+)$/);
+ carp (
+ "Prefetching multiple has_many rels ${last} and ${pre} "
+ .(length($as_prefix)
+ ? "at the same level (${as_prefix}) "
+ : "at top level "
+ )
+ . 'will currently disrupt both the functionality of $rs->count(), '
+ . 'and the amount of objects retrievable via $rs->next(). '
+ . 'Use at your own risk.'
+ );
+ }
#my @col = map { (/^self\.(.+)$/ ? ("${as_prefix}.$1") : ()); }
# values %{$rel_info->{cond}};
$collapse->{".${as_prefix}${pre}"} = [ $rel_source->primary_columns ];
Set the class of the resultset, this is useful if you want to create your
own resultset methods. Create your own class derived from
-L<DBIx::Class::ResultSet>, and set it here.
+L<DBIx::Class::ResultSet>, and set it here. If called with no arguments,
+this method returns the name of the existing resultset class, if one
+exists.
=head2 resultset_attributes
}
}
+=head2 sqlt_deploy_hook($sqlt_table)
+
+An optional sub which you can declare in your own Schema class that will get
+passed the L<SQL::Translator::Schema::Table> object when you deploy the schema
+via L</create_ddl_dir> or L</deploy>.
+
+For an example of what you can do with this, see
+L<DBIx::Class::Manual::Cookbook/Adding Indexes And Functions To Your SQL>.
+
=head1 AUTHORS
Matt S. Trout <mst@shadowcatsystems.co.uk>