sub add_columns {
my ($class, @cols) = @_;
- return $class->result_source_instance->add_columns(map lc, @cols);
+ return $class->result_source->add_columns(map lc, @cols);
}
sub has_a {
sub add_columns {
my ($class, @cols) = @_;
- $class->result_source_instance->add_columns(@cols);
+ $class->result_source->add_columns(@cols);
}
sub _register_column_group {
}
}
-sub all_columns { return shift->result_source_instance->columns; }
+sub all_columns { return shift->result_source->columns; }
sub primary_column {
my ($class) = @_;
$sth->execute(@$execute_args);
- my @ret;
+ my (@ret, $rsrc);
while (my $row = $sth->fetchrow_hashref) {
- push(@ret, $class->inflate_result($class->result_source_instance, $row));
+ push(@ret, $class->inflate_result(
+ ( $rsrc ||= $class->result_source ),
+ $row
+ ));
}
return @ret;
}
else {
$self->belongs_to($col, $f_class);
- $rel_info = $self->result_source_instance->relationship_info($col);
+ $rel_info = $self->result_source->relationship_info($col);
}
$rel_info->{args} = \%args;
if( !$f_key and !@f_method ) {
$class->ensure_class_loaded($f_class);
- my $f_source = $f_class->result_source_instance;
+ my $f_source = $f_class->result_source;
($f_key) = grep { $f_source->relationship_info($_)->{class} eq $class }
$f_source->relationships;
}
$class->next::method($rel, $f_class, $f_key, $args);
- my $rel_info = $class->result_source_instance->relationship_info($rel);
+ my $rel_info = $class->result_source->relationship_info($rel);
$args->{mapping} = \@f_method;
$args->{foreign_key} = $f_key;
$rel_info->{args} = $args;
{ proxy => \@columns });
}
- my $rel_info = $class->result_source_instance->relationship_info($rel);
+ my $rel_info = $class->result_source->relationship_info($rel);
$rel_info->{args}{import} = \@columns;
$class->_extend_meta(
=cut
sub resultset_instance {
- $_[0]->result_source_instance->resultset
+ $_[0]->result_source->resultset
}
=begin hidden
# Yep. this is horrific. Basically what's happening here is that
# (with good reason) DBIx::Class::Schema copies the result source for
# registration. Because we have a retarded setup order forced on us we need
-# to actually make our ->result_source_instance -be- the source used, and we
+# to actually make our ->result_source -be- the source used, and we
# need to get the source name and schema into ourselves. So this makes it
# happen.
$self->throw_exception("InflateColumn can not be used on a column with a declared FilterColumn filter")
if defined $colinfo->{_filter_info} and $self->isa('DBIx::Class::FilterColumn');
- $self->throw_exception("No such column $col to inflate")
- unless $self->result_source_instance->has_column($col);
$self->throw_exception("inflate_column needs attr hashref")
unless ref $attrs eq 'HASH';
+
$colinfo->{_inflate_info} = $attrs;
my $acc = $colinfo->{accessor};
$self->mk_group_accessors('inflated_column' => [ (defined $acc ? $acc : $col), $col]);
#
# do not attempt to deploy() this view
- __PACKAGE__->result_source_instance->is_virtual(1);
+ __PACKAGE__->result_source->is_virtual(1);
- __PACKAGE__->result_source_instance->view_definition(q[
+ __PACKAGE__->result_source->view_definition(q[
SELECT u.* FROM user u
INNER JOIN user_friends f ON u.id = f.user_id
WHERE f.friend_user_id = ?
$class->throw_exception(
"No such column '$f_key' declared yet on ${class} ($guess)"
- ) unless $class->result_source_instance->has_column($f_key);
+ ) unless $class->result_source->has_column($f_key);
$class->ensure_class_loaded($f_class);
my $f_rsrc = dbic_internal_try {
- $f_class->result_source_instance;
+ $f_class->result_source;
}
catch {
$class->throw_exception(
"Foreign class '$f_class' does not seem to be a Result class "
- . "(or it simply did not load entirely due to a circular relation chain)"
+ . "(or it simply did not load entirely due to a circular relation chain): $_"
);
};
and
(keys %$cond)[0] =~ /^foreign\./
and
- $class->result_source_instance->has_column($rel)
+ $class->result_source->has_column($rel)
) ? 'filter' : 'single';
my $fk_columns = ($acc_type eq 'single' and ref $cond eq 'HASH')
unless (ref $cond) {
- my $pri = $class->result_source_instance->_single_pri_col_or_die;
+ my $pri = $class->result_source->_single_pri_col_or_die;
my ($f_key,$guess);
if (defined $cond && length $cond) {
# FIXME - this check needs to be moved to schema-composition time...
# # only perform checks if the far side appears already loaded
-# if (my $f_rsrc = dbic_internal_try { $f_class->result_source_instance } ) {
+# if (my $f_rsrc = dbic_internal_try { $f_class->result_source } ) {
# $class->throw_exception(
# "No such column '$f_key' on foreign class ${f_class} ($guess)"
# ) if !$f_rsrc->has_column($f_key);
sub _has_one {
my ($class, $join_type, $rel, $f_class, $cond, $attrs) = @_;
unless (ref $cond) {
- my $pri = $class->result_source_instance->_single_pri_col_or_die;
+ my $pri = $class->result_source->_single_pri_col_or_die;
my ($f_key,$guess,$f_rsrc);
if (defined $cond && length $cond) {
$class->ensure_class_loaded($f_class);
$f_rsrc = dbic_internal_try {
- my $r = $f_class->result_source_instance;
+ my $r = $f_class->result_source;
die "There got to be some columns by now... (exception caught and rewritten by catch below)"
unless $r->columns;
$r;
# FIXME - this check needs to be moved to schema-composition time...
# # only perform checks if the far side was not preloaded above *AND*
-# # appears to have been loaded by something else (has a rsrc_instance)
-# if (! $f_rsrc and $f_rsrc = dbic_internal_try { $f_class->result_source_instance }) {
+# # appears to have been loaded by something else (has a rsrc)
+# if (! $f_rsrc and $f_rsrc = dbic_internal_try { $f_class->result_source }) {
# $class->throw_exception(
# "No such column '$f_key' on foreign class ${f_class} ($guess)"
# ) if !$f_rsrc->has_column($f_key);
my $self = shift;
my $resultset_class = $self . $self->table_resultset_class_suffix;
no strict 'refs';
- if (@{"$resultset_class\::ISA"}) {
- $self->result_source_instance->resultset_class($resultset_class);
- } else {
- $self->result_source_instance->resultset_class
- ($self->base_resultset_class);
- }
+ $self->result_source->resultset_class(
+ ( scalar @{"${resultset_class}::ISA"} )
+ ? $resultset_class
+ : $self->base_resultset_class
+ );
}
=head1 FURTHER QUESTIONS?
__PACKAGE__->table_class('DBIx::Class::ResultSource::View');
__PACKAGE__->table('year2000cds');
- __PACKAGE__->result_source_instance->is_virtual(1);
- __PACKAGE__->result_source_instance->view_definition(
+ __PACKAGE__->result_source->is_virtual(1);
+ __PACKAGE__->result_source->view_definition(
"SELECT cdid, artist, title FROM cd WHERE year ='2000'"
);
=back
- __PACKAGE__->result_source_instance->sqlt_deploy_callback('mycallbackmethod');
+ __PACKAGE__->result_source->sqlt_deploy_callback('mycallbackmethod');
or
- __PACKAGE__->result_source_instance->sqlt_deploy_callback(sub {
+ __PACKAGE__->result_source->sqlt_deploy_callback(sub {
my ($source_instance, $sqlt_table) = @_;
...
} );
else {
my $class = $self->relationship_info($rel)->{class};
$self->ensure_class_loaded($class);
- $class->result_source_instance;
+ $class->result_source;
}
}
__PACKAGE__->table_class('DBIx::Class::ResultSource::View');
__PACKAGE__->table('year2000cds');
- __PACKAGE__->result_source_instance->is_virtual(1);
- __PACKAGE__->result_source_instance->view_definition(
+ __PACKAGE__->result_source->is_virtual(1);
+ __PACKAGE__->result_source->view_definition(
"SELECT cdid, artist, title FROM cd WHERE year ='2000'"
);
__PACKAGE__->add_columns(
If you modified the schema to include a placeholder
- __PACKAGE__->result_source_instance->view_definition(
+ __PACKAGE__->result_source->view_definition(
"SELECT cdid, artist, title FROM cd WHERE year = ?"
);
and ensuring you have is_virtual set to true:
- __PACKAGE__->result_source_instance->is_virtual(1);
+ __PACKAGE__->result_source->is_virtual(1);
You could now say:
=head2 is_virtual
- __PACKAGE__->result_source_instance->is_virtual(1);
+ __PACKAGE__->result_source->is_virtual(1);
Set to true for a virtual view, false or unset for a real
database-based view.
=head2 view_definition
- __PACKAGE__->result_source_instance->view_definition(
+ __PACKAGE__->result_source->view_definition(
"SELECT cdid, artist, title FROM cd WHERE year ='2000'"
);
=head2 deploy_depends_on
- __PACKAGE__->result_source_instance->deploy_depends_on(
+ __PACKAGE__->result_source->deploy_depends_on(
["MyApp::Schema::Result::Year","MyApp::Schema::Result::CD"]
);
sub add_columns {
my ($class, @cols) = @_;
- my $source = $class->result_source_instance;
+ my $source = $class->result_source;
$source->add_columns(@cols);
my $colinfos;
sub add_relationship {
my ($class, $rel, @rest) = @_;
- my $source = $class->result_source_instance;
+ my $source = $class->result_source;
$source->add_relationship($rel => @rest);
$class->register_relationship($rel => $source->relationship_info($rel));
}
# legacy resultset_class accessor, seems to be used by cdbi only
sub iterator_class {
DBIx::Class::_ENV_::ASSERT_NO_INTERNAL_INDIRECT_CALLS and fail_on_internal_call;
- shift->result_source_instance->resultset_class(@_)
+ shift->result_source->resultset_class(@_)
}
for my $method_to_proxy (qw/
/) {
quote_sub __PACKAGE__."::$method_to_proxy", sprintf( <<'EOC', $method_to_proxy );
DBIx::Class::_ENV_::ASSERT_NO_INTERNAL_INDIRECT_CALLS and DBIx::Class::_Util::fail_on_internal_call;
- shift->result_source_instance->%s (@_);
+
+ shift->result_source->%s (@_);
EOC
}
=cut
sub table {
- return $_[0]->result_source_instance->name unless @_ > 1;
+ return $_[0]->result_source->name unless @_ > 1;
my ($class, $table) = @_;
$rsrc ||= $h->resolve;
}
- $new->result_source($rsrc) if $rsrc;
+ $new->result_source_instance($rsrc) if $rsrc;
if (my $col_from_rel = delete $attrs->{-cols_from_relations}) {
@{$new->{_ignore_at_insert}={}}{@$col_from_rel} = ();
$self->in_storage(0);
}
else {
- my $rsrc = dbic_internal_try { $self->result_source_instance }
- or $self->throw_exception("Can't do class delete without a ResultSource instance");
-
my $attrs = @_ > 1 && ref $_[$#_] eq 'HASH' ? { %{pop(@_)} } : {};
my $query = ref $_[0] eq 'HASH' ? $_[0] : {@_};
- $rsrc->resultset->search(@_)->delete;
+ $self->result_source->resultset->search_rs(@_)->delete;
}
return $self;
}
my $new = { _column_data => $col_data };
bless $new, ref $self;
- $new->result_source($rsrc);
+ $new->result_source_instance($rsrc);
$new->set_inflated_columns($changes);
$new->insert;
=cut
sub result_source {
+ # While getter calls are routed through here for sensible exception text
+ # it makes no sense to have setters do the same thing
+ DBIx::Class::_ENV_::ASSERT_NO_INTERNAL_INDIRECT_CALLS
+ and
+ @_ > 1
+ and
+ fail_on_internal_call;
+
# this is essentially a `shift->result_source_instance(@_)` with handholding
&{
$_[0]->can('result_source_instance')
||
$_[0]->throw_exception(
- "No result source instance registered for '@{[ $_[0] ]}', did you forget to call @{[ ref $_[0] || $_[0] ]}->table(...) ?"
+ "No ResultSource instance registered for '@{[ $_[0] ]}', did you forget to call @{[ ref $_[0] || $_[0] ]}->table(...) ?"
)
};
}
if (
! DBIx::Class::_Util::in_internal_try
and
- my $rsrc = dbic_internal_try { $self->result_source }
+ # FIXME - the try is 99% superfluous, but just in case
+ my $rsrc = dbic_internal_try { $self->result_source_instance }
) {
$rsrc->throw_exception(@_)
}
my $rs_class = ref ($_[0]) || $_[0];
return dbic_internal_try {
- $rs_class->result_source_instance
+ $rs_class->result_source
} catch {
$me->throw_exception (
"Attempt to load_namespaces() class $rs_class failed - are you sure this is a real Result Class?: $_"
Registers a class which isa DBIx::Class::ResultSourceProxy. Equivalent to
calling:
- $schema->register_source($source_name, $component_class->result_source_instance);
+ $schema->register_source($source_name, $component_class->result_source);
=cut
sub register_class {
my ($self, $source_name, $to_register) = @_;
- $self->register_source($source_name => $to_register->result_source_instance);
+ $self->register_source($source_name => $to_register->result_source);
}
=head2 register_source
if (@_) {
foreach my $col (@_) {
$self->throw_exception("column $col doesn't exist")
- unless $self->result_source_instance->has_column($col);
+ unless $self->result_source->has_column($col);
}
return $self->_utf8_columns({ map { $_ => 1 } @_ });
} else {
{
package DB;
$fr = [ CORE::caller(1) ];
- $argdesc = ref $DB::args[0]
- ? DBIx::Class::_Util::refdesc($DB::args[0])
- : ( $DB::args[0] . '' )
+ $argdesc =
+ ( not defined $DB::args[0] ) ? 'UNAVAILABLE'
+ : ( length ref $DB::args[0] ) ? DBIx::Class::_Util::refdesc($DB::args[0])
+ : $DB::args[0] . ''
;
};
;
if (
- $argdesc
+ defined $fr->[0]
and
$check_fr->[0] =~ /^(?:DBIx::Class|DBICx::)/
and
dbg DEBUG_TEST_CONCURRENCY_LOCKS PEEPEENESS
);
use DBICTest::Util::LeakTracer qw/populate_weakregistry assert_empty_weakregistry/;
+
+# The actual ASSERT logic is in BaseSchema for pesky load-order reasons
+# Hence run this through once, *before* DBICTest::Schema and friends load
+BEGIN {
+ if (
+ DBIx::Class::_ENV_::ASSERT_NO_ERRONEOUS_METAINSTANCE_USE
+ or
+ DBIx::Class::_ENV_::ASSERT_NO_INTERNAL_INDIRECT_CALLS
+ ) {
+ require DBIx::Class::Row;
+ require DBICTest::BaseSchema;
+ DBICTest::BaseSchema->connect( sub {} );
+ }
+}
+
use DBICTest::Schema;
use DBIx::Class::_Util qw( detected_reinvoked_destructor scope_guard modver_gt_or_eq );
use Carp;
my $clan_connect_caller = '*UNKNOWN*';
my $i;
- while ( my ($pack, $file, $line) = caller(++$i) ) {
+ while ( my ($pack, $file, $line) = CORE::caller(++$i) ) {
next if $file eq __FILE__;
next if $pack =~ /^DBIx::Class|^Try::Tiny/;
$clan_connect_caller = "$file line $line";
use Fcntl qw(:DEFAULT :seek :flock);
use IO::Handle ();
-use DBIx::Class::_Util 'scope_guard';
+use DBIx::Class::_Util qw( emit_loud_diag scope_guard set_subname get_subname );
use DBICTest::Util::LeakTracer qw(populate_weakregistry assert_empty_weakregistry);
use DBICTest::Util qw( local_umask tmpdir await_flock dbg DEBUG_TEST_CONCURRENCY_LOCKS );
+use Scalar::Util qw( refaddr weaken );
use namespace::clean;
if( $ENV{DBICTEST_ASSERT_NO_SPURIOUS_EXCEPTION_ACTION} ) {
}
}
-my $weak_registry = {};
+my ( $weak_registry, $assertion_arounds ) = ( {}, {} );
+
+sub DBICTest::__RsrcRedefiner_iThreads_handler__::CLONE {
+ if( DBIx::Class::_ENV_::ASSERT_NO_ERRONEOUS_METAINSTANCE_USE ) {
+ %$assertion_arounds = map {
+ (defined $_)
+ ? ( refaddr($_) => $_ )
+ : ()
+ } values %$assertion_arounds;
+
+ weaken($_) for values %$assertion_arounds;
+ }
+}
sub connection {
my $self = shift->next::method(@_);
]);
}
+ #
+ # Check an explicit level of indirection: makes sure that folks doing
+ # use `base "DBIx::Class::Core"; __PACKAGE__->add_column("foo")`
+ # will see the correct error message
+ #
+ # In the future this all is likely to be folded into a single method in
+ # some way, but that's a fight for another maint
+ #
+ if( DBIx::Class::_ENV_::ASSERT_NO_ERRONEOUS_METAINSTANCE_USE ) {
+
+ for my $class_of_interest (
+ 'DBIx::Class::Row',
+ map { $self->class($_) } ($self->sources)
+ ) {
+
+ my $orig_rsrc = $class_of_interest->can('result_source')
+ or die "How did we get here?!";
+
+ unless ( $assertion_arounds->{refaddr $orig_rsrc} ) {
+
+ my ($origin) = get_subname($orig_rsrc);
+
+ no warnings 'redefine';
+ no strict 'refs';
+
+ *{"${origin}::result_source"} = my $replacement = set_subname "${origin}::result_source" => sub {
+
+
+ @_ > 1
+ and
+ (CORE::caller(0))[1] !~ / (?: ^ | [\/\\] ) x?t [\/\\] .+? \.t $ /x
+ and
+ emit_loud_diag(
+ msg => 'Incorrect indirect call of result_source() as setter must be changed to result_source_instance()',
+ confess => 1,
+ );
+
+
+ grep {
+ ! (CORE::caller($_))[7]
+ and
+ ( (CORE::caller($_))[3] || '' ) eq '(eval)'
+ and
+ ( (CORE::caller($_))[1] || '' ) !~ / (?: ^ | [\/\\] ) x?t [\/\\] .+? \.t $ /x
+ } (0..2)
+ and
+ # these evals are legit
+ ( (CORE::caller(4))[3] || '' ) !~ /^ (?:
+ DBIx::Class::Schema::_ns_get_rsrc_instance
+ |
+ DBIx::Class::Relationship::BelongsTo::belongs_to
+ |
+ DBIx::Class::Relationship::HasOne::_has_one
+ |
+ Class::C3::Componentised::.+
+ ) $/x
+ and
+ emit_loud_diag(
+ # not much else we can do (aside from exit(1) which is too obnoxious)
+ msg => 'Incorrect call of result_source() in an eval',
+ );
+
+
+ &$orig_rsrc;
+ };
+
+ weaken( $assertion_arounds->{refaddr $replacement} = $replacement );
+ }
+
+
+ # no rsrc_instance to mangle
+ next if $class_of_interest eq 'DBIx::Class::Row';
+
+
+ my $orig_rsrc_instance = $class_of_interest->can('result_source_instance')
+ or die "How did we get here?!";
+
+ # Do the around() per definition-site as result_source_instance is a CAG inherited cref
+ unless ( $assertion_arounds->{refaddr $orig_rsrc_instance} ) {
+
+ my ($origin) = get_subname($orig_rsrc_instance);
+
+ no warnings 'redefine';
+ no strict 'refs';
+
+ *{"${origin}::result_source_instance"} = my $replacement = set_subname "${origin}::result_source_instance" => sub {
+
+
+ @_ == 1
+ and
+ # special cased as we do not care whether there is a source
+ ( (CORE::caller(4))[3] || '' ) ne 'DBIx::Class::Schema::_register_source'
+ and
+ # special case because I am paranoid
+ ( (CORE::caller(4))[3] || '' ) ne 'DBIx::Class::Row::throw_exception'
+ and
+ ( (CORE::caller(1))[3] || '' ) !~ / ^ DBIx::Class:: (?:
+ Row::result_source
+ |
+ Row::throw_exception
+ |
+ ResultSourceProxy::Table:: (?: _init_result_source_instance | table )
+ |
+ ResultSourceHandle::STORABLE_thaw
+ ) $ /x
+ and
+ (CORE::caller(0))[1] !~ / (?: ^ | [\/\\] ) x?t [\/\\] .+? \.t $ /x
+ and
+ emit_loud_diag(
+ msg => 'Incorrect direct call of result_source_instance() as getter must be changed to result_source()',
+ confess => 1
+ );
+
+
+ grep {
+ ! (CORE::caller($_))[7]
+ and
+ ( (CORE::caller($_))[3] || '' ) eq '(eval)'
+ and
+ ( (CORE::caller($_))[1] || '' ) !~ / (?: ^ | [\/\\] ) x?t [\/\\] .+? \.t $ /x
+ } (0..2)
+ and
+ # special cased as we do not care whether there is a source
+ ( (CORE::caller(4))[3] || '' ) ne 'DBIx::Class::Schema::_register_source'
+ and
+ # special case because I am paranoid
+ ( (CORE::caller(4))[3] || '' ) ne 'DBIx::Class::Row::throw_exception'
+ and
+ # special case for Storable, which in turn calls from an eval
+ ( (CORE::caller(1))[3] || '' ) ne 'DBIx::Class::ResultSourceHandle::STORABLE_thaw'
+ and
+ emit_loud_diag(
+ # not much else we can do (aside from exit(1) which is too obnoxious)
+ msg => 'Incorrect call of result_source_instance() in an eval',
+ skip_frames => 1,
+ show_dups => 1,
+ );
+
+ &$orig_rsrc_instance;
+ };
+
+ weaken( $assertion_arounds->{refaddr $replacement} = $replacement );
+ }
+
+ }
+
+ Class::C3::initialize if DBIx::Class::_ENV_::OLD_MRO;
+ }
+ #
+ # END Check an explicit level of indirection
+
return $self;
}
BEGIN { do "./t/lib/ANFANG.pm" or die ( $@ || $! ) }
+BEGIN { $ENV{DBIC_ASSERT_NO_ERRONEOUS_METAINSTANCE_USE} = 0 }
+
use strict;
use warnings;
no warnings 'qw';