DBIx-Class
view release on metacpan or search on metacpan
lib/DBIx/Class/ResultSource.pm view on Meta::CPAN
package DBIx::Class::ResultSource;
use strict;
use warnings;
use base qw/DBIx::Class::ResultSource::RowParser DBIx::Class/;
use DBIx::Class::ResultSet;
use DBIx::Class::ResultSourceHandle;
use DBIx::Class::Carp;
use DBIx::Class::_Util 'UNRESOLVABLE_CONDITION';
use SQL::Abstract::Util 'is_literal_value';
use Devel::GlobalDestruction;
use Try::Tiny;
use Scalar::Util qw/blessed weaken isweak/;
use namespace::clean;
__PACKAGE__->mk_group_accessors(simple => qw/
source_name name source_info
_ordered_columns _columns _primaries _unique_constraints
_relationships resultset_attributes
column_info_from_storage
/);
__PACKAGE__->mk_group_accessors(component_class => qw/
resultset_class
result_class
/);
__PACKAGE__->mk_classdata( sqlt_deploy_callback => 'default_sqlt_deploy_hook' );
=head1 NAME
DBIx::Class::ResultSource - Result source object
=head1 SYNOPSIS
# Create a table based result source, in a result class.
package MyApp::Schema::Result::Artist;
use base qw/DBIx::Class::Core/;
__PACKAGE__->table('artist');
__PACKAGE__->add_columns(qw/ artistid name /);
__PACKAGE__->set_primary_key('artistid');
__PACKAGE__->has_many(cds => 'MyApp::Schema::Result::CD');
1;
# Create a query (view) based result source, in a result class
package MyApp::Schema::Result::Year2000CDs;
use base qw/DBIx::Class::Core/;
__PACKAGE__->load_components('InflateColumn::DateTime');
__PACKAGE__->table_class('DBIx::Class::ResultSource::View');
__PACKAGE__->table('year2000cds');
__PACKAGE__->result_source_instance->is_virtual(1);
__PACKAGE__->result_source_instance->view_definition(
"SELECT cdid, artist, title FROM cd WHERE year ='2000'"
);
=head1 DESCRIPTION
A ResultSource is an object that represents a source of data for querying.
This class is a base class for various specialised types of result
sources, for example L<DBIx::Class::ResultSource::Table>. Table is the
default result source type, so one is created for you when defining a
result class as described in the synopsis above.
More specifically, the L<DBIx::Class::Core> base class pulls in the
L<DBIx::Class::ResultSourceProxy::Table> component, which defines
lib/DBIx/Class/ResultSource.pm view on Meta::CPAN
my ($self, $rel) = @_;
if( !$self->has_relationship( $rel ) ) {
$self->throw_exception("No such relationship '$rel' on " . $self->source_name);
}
return $self->schema->class($self->relationship_info($rel)->{source});
}
=head2 handle
=over 4
=item Arguments: none
=item Return Value: L<$source_handle|DBIx::Class::ResultSourceHandle>
=back
Obtain a new L<result source handle instance|DBIx::Class::ResultSourceHandle>
for this source. Used as a serializable pointer to this resultsource, as it is not
easy (nor advisable) to serialize CODErefs which may very well be present in e.g.
relationship definitions.
=cut
sub handle {
return DBIx::Class::ResultSourceHandle->new({
source_moniker => $_[0]->source_name,
# so that a detached thaw can be re-frozen
$_[0]->{_detached_thaw}
? ( _detached_source => $_[0] )
: ( schema => $_[0]->schema )
,
});
}
my $global_phase_destroy;
sub DESTROY {
### NO detected_reinvoked_destructor check
### This code very much relies on being called multuple times
return if $global_phase_destroy ||= in_global_destruction;
######
# !!! ACHTUNG !!!!
######
#
# Under no circumstances shall $_[0] be stored anywhere else (like copied to
# a lexical variable, or shifted, or anything else). Doing so will mess up
# the refcount of this particular result source, and will allow the $schema
# we are trying to save to reattach back to the source we are destroying.
# The relevant code checking refcounts is in ::Schema::DESTROY()
# if we are not a schema instance holder - we don't matter
return if(
! ref $_[0]->{schema}
or
isweak $_[0]->{schema}
);
# weaken our schema hold forcing the schema to find somewhere else to live
# during global destruction (if we have not yet bailed out) this will throw
# which will serve as a signal to not try doing anything else
# however beware - on older perls the exception seems randomly untrappable
# due to some weird race condition during thread joining :(((
local $@;
eval {
weaken $_[0]->{schema};
# if schema is still there reintroduce ourselves with strong refs back to us
if ($_[0]->{schema}) {
my $srcregs = $_[0]->{schema}->source_registrations;
for (keys %$srcregs) {
next unless $srcregs->{$_};
$srcregs->{$_} = $_[0] if $srcregs->{$_} == $_[0];
}
}
1;
} or do {
$global_phase_destroy = 1;
};
return;
}
sub STORABLE_freeze { Storable::nfreeze($_[0]->handle) }
sub STORABLE_thaw {
my ($self, $cloning, $ice) = @_;
%$self = %{ (Storable::thaw($ice))->resolve };
}
=head2 throw_exception
See L<DBIx::Class::Schema/"throw_exception">.
=cut
sub throw_exception {
my $self = shift;
$self->{schema}
? $self->{schema}->throw_exception(@_)
: DBIx::Class::Exception->throw(@_)
;
}
=head2 column_info_from_storage
=over
=item Arguments: 1/0 (default: 0)
=item Return Value: 1/0
=back
__PACKAGE__->column_info_from_storage(1);
Enables the on-demand automatic loading of the above column
metadata from storage as necessary. This is *deprecated*, and
should not be used. It will be removed before 1.0.
=head1 FURTHER QUESTIONS?
Check the list of L<additional DBIC resources|DBIx::Class/GETTING HELP/SUPPORT>.
( run in 0.922 second using v1.01-cache-2.11-cpan-39bf76dae61 )