Resolve $rsrc instance duality on metadata traversal
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / Schema.pm
CommitLineData
a02675cd 1package DBIx::Class::Schema;
2
3use strict;
4use warnings;
aa562407 5
64c50e81 6use base 'DBIx::Class';
7
70c28808 8use DBIx::Class::Carp;
9780718f 9use Try::Tiny;
aea59b74 10use Scalar::Util qw/weaken blessed/;
ddcc02d1 11use DBIx::Class::_Util qw(
12 refcount quote_sub scope_guard
13 is_exception dbic_internal_try
c40b5744 14 fail_on_internal_call emit_loud_diag
ddcc02d1 15);
d6b39e46 16use Devel::GlobalDestruction;
fd323bf1 17use namespace::clean;
a02675cd 18
e5053694 19__PACKAGE__->mk_group_accessors( inherited => qw( storage exception_action ) );
e5053694 20__PACKAGE__->mk_classaccessor('storage_type' => '::DBI');
21__PACKAGE__->mk_classaccessor('stacktrace' => $ENV{DBIC_TRACE} || 0);
22__PACKAGE__->mk_classaccessor('default_resultset_attributes' => {});
a02675cd 23
759a7f44 24# These two should have been private from the start but too late now
25# Undocumented on purpose, hopefully it won't ever be necessary to
26# screw with them
27__PACKAGE__->mk_classaccessor('class_mappings' => {});
28__PACKAGE__->mk_classaccessor('source_registrations' => {});
29
c2da098a 30=head1 NAME
31
32DBIx::Class::Schema - composable schemas
33
34=head1 SYNOPSIS
35
24d67825 36 package Library::Schema;
c2da098a 37 use base qw/DBIx::Class::Schema/;
bab77431 38
829517d4 39 # load all Result classes in Library/Schema/Result/
40 __PACKAGE__->load_namespaces();
c2da098a 41
829517d4 42 package Library::Schema::Result::CD;
d88ecca6 43 use base qw/DBIx::Class::Core/;
44
45 __PACKAGE__->load_components(qw/InflateColumn::DateTime/); # for example
24d67825 46 __PACKAGE__->table('cd');
c2da098a 47
5d9076f2 48 # Elsewhere in your code:
24d67825 49 my $schema1 = Library::Schema->connect(
a3d93194 50 $dsn,
51 $user,
52 $password,
ef131d82 53 { AutoCommit => 1 },
a3d93194 54 );
bab77431 55
24d67825 56 my $schema2 = Library::Schema->connect($coderef_returning_dbh);
c2da098a 57
829517d4 58 # fetch objects using Library::Schema::Result::DVD
24d67825 59 my $resultset = $schema1->resultset('DVD')->search( ... );
60 my @dvd_objects = $schema2->resultset('DVD')->search( ... );
c2da098a 61
62=head1 DESCRIPTION
63
a3d93194 64Creates database classes based on a schema. This is the recommended way to
65use L<DBIx::Class> and allows you to use more than one concurrent connection
66with your classes.
429bd4f1 67
03312470 68NB: If you're used to L<Class::DBI> it's worth reading the L</SYNOPSIS>
2053ab2a 69carefully, as DBIx::Class does things a little differently. Note in
03312470 70particular which module inherits off which.
71
829517d4 72=head1 SETUP METHODS
c2da098a 73
829517d4 74=head2 load_namespaces
87c4e602 75
27f01d1f 76=over 4
77
829517d4 78=item Arguments: %options?
27f01d1f 79
80=back
076652e8 81
a5bd5d88 82 package MyApp::Schema;
829517d4 83 __PACKAGE__->load_namespaces();
66d9ef6b 84
829517d4 85 __PACKAGE__->load_namespaces(
6f731572 86 result_namespace => 'Res',
87 resultset_namespace => 'RSet',
a5bd5d88 88 default_resultset_class => '+MyApp::Othernamespace::RSet',
6f731572 89 );
90
91With no arguments, this method uses L<Module::Find> to load all of the
92Result and ResultSet classes under the namespace of the schema from
93which it is called. For example, C<My::Schema> will by default find
94and load Result classes named C<My::Schema::Result::*> and ResultSet
95classes named C<My::Schema::ResultSet::*>.
96
97ResultSet classes are associated with Result class of the same name.
98For example, C<My::Schema::Result::CD> will get the ResultSet class
99C<My::Schema::ResultSet::CD> if it is present.
100
101Both Result and ResultSet namespaces are configurable via the
102C<result_namespace> and C<resultset_namespace> options.
076652e8 103
6f731572 104Another option, C<default_resultset_class> specifies a custom default
105ResultSet class for Result classes with no corresponding ResultSet.
c2da098a 106
6f731572 107All of the namespace and classname options are by default relative to
108the schema classname. To specify a fully-qualified name, prefix it
109with a literal C<+>. For example, C<+Other::NameSpace::Result>.
110
111=head3 Warnings
74b92d9a 112
672687db 113You will be warned if ResultSet classes are discovered for which there
829517d4 114are no matching Result classes like this:
87c4e602 115
829517d4 116 load_namespaces found ResultSet class $classname with no corresponding Result class
27f01d1f 117
5529838f 118If a ResultSource instance is found to already have a ResultSet class set
119using L<resultset_class|DBIx::Class::ResultSource/resultset_class> to some
120other class, you will be warned like this:
27f01d1f 121
5529838f 122 We found ResultSet class '$rs_class' for '$result_class', but it seems
123 that you had already set '$result_class' to use '$rs_set' instead
076652e8 124
6f731572 125=head3 Examples
2a4d9487 126
829517d4 127 # load My::Schema::Result::CD, My::Schema::Result::Artist,
128 # My::Schema::ResultSet::CD, etc...
129 My::Schema->load_namespaces;
2a4d9487 130
829517d4 131 # Override everything to use ugly names.
132 # In this example, if there is a My::Schema::Res::Foo, but no matching
133 # My::Schema::RSets::Foo, then Foo will have its
134 # resultset_class set to My::Schema::RSetBase
135 My::Schema->load_namespaces(
136 result_namespace => 'Res',
137 resultset_namespace => 'RSets',
138 default_resultset_class => 'RSetBase',
139 );
2a4d9487 140
829517d4 141 # Put things in other namespaces
142 My::Schema->load_namespaces(
143 result_namespace => '+Some::Place::Results',
144 resultset_namespace => '+Another::Place::RSets',
145 );
2a4d9487 146
6f731572 147To search multiple namespaces for either Result or ResultSet classes,
148use an arrayref of namespaces for that option. In the case that the
149same result (or resultset) class exists in multiple namespaces, later
150entries in the list of namespaces will override earlier ones.
2a4d9487 151
829517d4 152 My::Schema->load_namespaces(
153 # My::Schema::Results_C::Foo takes precedence over My::Schema::Results_B::Foo :
154 result_namespace => [ 'Results_A', 'Results_B', 'Results_C' ],
155 resultset_namespace => [ '+Some::Place::RSets', 'RSets' ],
156 );
2a4d9487 157
158=cut
159
829517d4 160# Pre-pends our classname to the given relative classname or
161# class namespace, unless there is a '+' prefix, which will
162# be stripped.
163sub _expand_relative_name {
164 my ($class, $name) = @_;
93d7452f 165 $name =~ s/^\+// or $name = "${class}::${name}";
829517d4 166 return $name;
2a4d9487 167}
168
f3405058 169# Finds all modules in the supplied namespace, or if omitted in the
170# namespace of $class. Untaints all findings as they can be assumed
171# to be safe
172sub _findallmod {
3b80fa31 173 require Module::Find;
93d7452f 174 return map
175 { $_ =~ /(.+)/ } # untaint result
176 Module::Find::findallmod( $_[1] || ref $_[0] || $_[0] )
177 ;
f3405058 178}
179
829517d4 180# returns a hash of $shortname => $fullname for every package
b488020e 181# found in the given namespaces ($shortname is with the $fullname's
182# namespace stripped off)
829517d4 183sub _map_namespaces {
93d7452f 184 my ($me, $namespaces) = @_;
185
186 my %res;
187 for my $ns (@$namespaces) {
188 $res{ substr($_, length "${ns}::") } = $_
189 for $me->_findallmod($ns);
0dc79249 190 }
27f01d1f 191
93d7452f 192 \%res;
ea20d0fd 193}
194
b488020e 195# returns the result_source_instance for the passed class/object,
196# or dies with an informative message (used by load_namespaces)
197sub _ns_get_rsrc_instance {
dee99c24 198 my $me = shift;
199 my $rs_class = ref ($_[0]) || $_[0];
200
ddcc02d1 201 return dbic_internal_try {
dee99c24 202 $rs_class->result_source_instance
203 } catch {
204 $me->throw_exception (
205 "Attempt to load_namespaces() class $rs_class failed - are you sure this is a real Result Class?: $_"
b488020e 206 );
dee99c24 207 };
b488020e 208}
209
829517d4 210sub load_namespaces {
211 my ($class, %args) = @_;
0dc79249 212
829517d4 213 my $result_namespace = delete $args{result_namespace} || 'Result';
214 my $resultset_namespace = delete $args{resultset_namespace} || 'ResultSet';
93d7452f 215
829517d4 216 my $default_resultset_class = delete $args{default_resultset_class};
0dc79249 217
93d7452f 218 $default_resultset_class = $class->_expand_relative_name($default_resultset_class)
219 if $default_resultset_class;
220
829517d4 221 $class->throw_exception('load_namespaces: unknown option(s): '
222 . join(q{,}, map { qq{'$_'} } keys %args))
223 if scalar keys %args;
0dc79249 224
829517d4 225 for my $arg ($result_namespace, $resultset_namespace) {
93d7452f 226 $arg = [ $arg ] if ( $arg and ! ref $arg );
9b1ba0f2 227
829517d4 228 $class->throw_exception('load_namespaces: namespace arguments must be '
229 . 'a simple string or an arrayref')
230 if ref($arg) ne 'ARRAY';
9b1ba0f2 231
829517d4 232 $_ = $class->_expand_relative_name($_) for (@$arg);
233 }
ea20d0fd 234
93d7452f 235 my $results_by_source_name = $class->_map_namespaces($result_namespace);
236 my $resultsets_by_source_name = $class->_map_namespaces($resultset_namespace);
27f01d1f 237
829517d4 238 my @to_register;
239 {
87bf71d5 240 no warnings qw/redefine/;
241 local *Class::C3::reinitialize = sub { } if DBIx::Class::_ENV_::OLD_MRO;
242 use warnings qw/redefine/;
27f01d1f 243
3988ce40 244 # ensure classes are loaded and attached in inheritance order
93d7452f 245 for my $result_class (values %$results_by_source_name) {
246 $class->ensure_class_loaded($result_class);
f5ef5fa1 247 }
3988ce40 248 my %inh_idx;
93d7452f 249 my @source_names_by_subclass_last = sort {
3988ce40 250
251 ($inh_idx{$a} ||=
93d7452f 252 scalar @{mro::get_linear_isa( $results_by_source_name->{$a} )}
3988ce40 253 )
254
255 <=>
256
257 ($inh_idx{$b} ||=
93d7452f 258 scalar @{mro::get_linear_isa( $results_by_source_name->{$b} )}
3988ce40 259 )
260
93d7452f 261 } keys(%$results_by_source_name);
3988ce40 262
93d7452f 263 foreach my $source_name (@source_names_by_subclass_last) {
264 my $result_class = $results_by_source_name->{$source_name};
82b01c38 265
93d7452f 266 my $preset_resultset_class = $class->_ns_get_rsrc_instance ($result_class)->resultset_class;
267 my $found_resultset_class = delete $resultsets_by_source_name->{$source_name};
3988ce40 268
93d7452f 269 if($preset_resultset_class && $preset_resultset_class ne 'DBIx::Class::ResultSet') {
270 if($found_resultset_class && $found_resultset_class ne $preset_resultset_class) {
271 carp "We found ResultSet class '$found_resultset_class' matching '$results_by_source_name->{$source_name}', but it seems "
272 . "that you had already set the '$results_by_source_name->{$source_name}' resultet to '$preset_resultset_class' instead";
829517d4 273 }
274 }
93d7452f 275 # elsif - there may be *no* default_resultset_class, in which case we fallback to
276 # DBIx::Class::Resultset and there is nothing to check
277 elsif($found_resultset_class ||= $default_resultset_class) {
278 $class->ensure_class_loaded($found_resultset_class);
279 if(!$found_resultset_class->isa("DBIx::Class::ResultSet")) {
280 carp "load_namespaces found ResultSet class '$found_resultset_class' that does not subclass DBIx::Class::ResultSet";
1d3108a4 281 }
282
93d7452f 283 $class->_ns_get_rsrc_instance ($result_class)->resultset_class($found_resultset_class);
829517d4 284 }
82b01c38 285
93d7452f 286 my $source_name = $class->_ns_get_rsrc_instance ($result_class)->source_name || $source_name;
0e6c5d58 287
288 push(@to_register, [ $source_name, $result_class ]);
829517d4 289 }
290 }
ea20d0fd 291
93d7452f 292 foreach (sort keys %$resultsets_by_source_name) {
293 carp "load_namespaces found ResultSet class '$resultsets_by_source_name->{$_}' "
294 .'with no corresponding Result class';
829517d4 295 }
ea20d0fd 296
87bf71d5 297 Class::C3->reinitialize if DBIx::Class::_ENV_::OLD_MRO;
298
829517d4 299 $class->register_class(@$_) for (@to_register);
ea20d0fd 300
829517d4 301 return;
ea20d0fd 302}
303
87c4e602 304=head2 load_classes
305
27f01d1f 306=over 4
307
308=item Arguments: @classes?, { $namespace => [ @classes ] }+
309
310=back
076652e8 311
1ab61457 312L</load_classes> is an alternative method to L</load_namespaces>, both of
313which serve similar purposes, each with different advantages and disadvantages.
314In the general case you should use L</load_namespaces>, unless you need to
315be able to specify that only specific classes are loaded at runtime.
829517d4 316
82b01c38 317With no arguments, this method uses L<Module::Find> to find all classes under
318the schema's namespace. Otherwise, this method loads the classes you specify
319(using L<use>), and registers them (using L</"register_class">).
076652e8 320
2053ab2a 321It is possible to comment out classes with a leading C<#>, but note that perl
322will think it's a mistake (trying to use a comment in a qw list), so you'll
323need to add C<no warnings 'qw';> before your load_classes call.
5ce32fc1 324
829517d4 325If any classes found do not appear to be Result class files, you will
326get the following warning:
327
fd323bf1 328 Failed to load $comp_class. Can't find source_name method. Is
829517d4 329 $comp_class really a full DBIC result class? Fix it, move it elsewhere,
330 or make your load_classes call more specific.
331
2053ab2a 332Example:
82b01c38 333
334 My::Schema->load_classes(); # loads My::Schema::CD, My::Schema::Artist,
75d07914 335 # etc. (anything under the My::Schema namespace)
82b01c38 336
337 # loads My::Schema::CD, My::Schema::Artist, Other::Namespace::Producer but
338 # not Other::Namespace::LinerNotes nor My::Schema::Track
339 My::Schema->load_classes(qw/ CD Artist #Track /, {
340 Other::Namespace => [qw/ Producer #LinerNotes /],
341 });
342
076652e8 343=cut
344
a02675cd 345sub load_classes {
5ce32fc1 346 my ($class, @params) = @_;
bab77431 347
5ce32fc1 348 my %comps_for;
bab77431 349
5ce32fc1 350 if (@params) {
351 foreach my $param (@params) {
352 if (ref $param eq 'ARRAY') {
353 # filter out commented entries
354 my @modules = grep { $_ !~ /^#/ } @$param;
bab77431 355
5ce32fc1 356 push (@{$comps_for{$class}}, @modules);
357 }
358 elsif (ref $param eq 'HASH') {
359 # more than one namespace possible
360 for my $comp ( keys %$param ) {
361 # filter out commented entries
362 my @modules = grep { $_ !~ /^#/ } @{$param->{$comp}};
363
364 push (@{$comps_for{$comp}}, @modules);
365 }
366 }
367 else {
368 # filter out commented entries
369 push (@{$comps_for{$class}}, $param) if $param !~ /^#/;
370 }
371 }
372 } else {
bc0c9800 373 my @comp = map { substr $_, length "${class}::" }
93d7452f 374 $class->_findallmod($class);
5ce32fc1 375 $comps_for{$class} = \@comp;
41a6f8c0 376 }
5ce32fc1 377
e6efde04 378 my @to_register;
379 {
380 no warnings qw/redefine/;
87bf71d5 381 local *Class::C3::reinitialize = sub { } if DBIx::Class::_ENV_::OLD_MRO;
382 use warnings qw/redefine/;
383
e6efde04 384 foreach my $prefix (keys %comps_for) {
385 foreach my $comp (@{$comps_for{$prefix}||[]}) {
386 my $comp_class = "${prefix}::${comp}";
c037c03a 387 $class->ensure_class_loaded($comp_class);
bab77431 388
89271e56 389 my $snsub = $comp_class->can('source_name');
390 if(! $snsub ) {
341d5ede 391 carp "Failed to load $comp_class. Can't find source_name method. Is $comp_class really a full DBIC result class? Fix it, move it elsewhere, or make your load_classes call more specific.";
89271e56 392 next;
393 }
394 $comp = $snsub->($comp_class) || $comp;
395
93405cf0 396 push(@to_register, [ $comp, $comp_class ]);
bfb2bd4f 397 }
5ce32fc1 398 }
a02675cd 399 }
87bf71d5 400 Class::C3->reinitialize if DBIx::Class::_ENV_::OLD_MRO;
e6efde04 401
402 foreach my $to (@to_register) {
403 $class->register_class(@$to);
e6efde04 404 }
a02675cd 405}
406
829517d4 407=head2 storage_type
2374c5ff 408
409=over 4
410
829517d4 411=item Arguments: $storage_type|{$storage_type, \%args}
412
fb13a49f 413=item Return Value: $storage_type|{$storage_type, \%args}
829517d4 414
415=item Default value: DBIx::Class::Storage::DBI
2374c5ff 416
417=back
418
829517d4 419Set the storage class that will be instantiated when L</connect> is called.
420If the classname starts with C<::>, the prefix C<DBIx::Class::Storage> is
95787afe 421assumed by L</connect>.
2374c5ff 422
829517d4 423You want to use this to set subclasses of L<DBIx::Class::Storage::DBI>
95787afe 424in cases where the appropriate subclass is not autodetected.
85bd0538 425
829517d4 426If your storage type requires instantiation arguments, those are
427defined as a second argument in the form of a hashref and the entire
428value needs to be wrapped into an arrayref or a hashref. We support
429both types of refs here in order to play nice with your
430Config::[class] or your choice. See
431L<DBIx::Class::Storage::DBI::Replicated> for an example of this.
0f4ec1d2 432
759a7f44 433=head2 default_resultset_attributes
434
435=over 4
436
437=item Arguments: L<\%attrs|DBIx::Class::ResultSet/ATTRIBUTES>
438
439=item Return Value: L<\%attrs|DBIx::Class::ResultSet/ATTRIBUTES>
440
441=item Default value: None
442
443=back
444
445Like L<DBIx::Class::ResultSource/resultset_attributes> stores a collection
446of resultset attributes, to be used as defaults for B<every> ResultSet
447instance schema-wide. The same list of CAVEATS and WARNINGS applies, with
448the extra downside of these defaults being practically inescapable: you will
449B<not> be able to derive a ResultSet instance with these attributes unset.
450
451Example:
452
453 package My::Schema;
454 use base qw/DBIx::Class::Schema/;
455 __PACKAGE__->default_resultset_attributes( { software_limit => 1 } );
456
829517d4 457=head2 exception_action
f017c022 458
829517d4 459=over 4
0f4ec1d2 460
829517d4 461=item Arguments: $code_reference
f017c022 462
fb13a49f 463=item Return Value: $code_reference
85bd0538 464
829517d4 465=item Default value: None
2374c5ff 466
829517d4 467=back
f017c022 468
c3e9f718 469When L</throw_exception> is invoked and L</exception_action> is set to a code
470reference, this reference will be called instead of
471L<DBIx::Class::Exception/throw>, with the exception message passed as the only
472argument.
f017c022 473
c3e9f718 474Your custom throw code B<must> rethrow the exception, as L</throw_exception> is
475an integral part of DBIC's internal execution control flow.
f017c022 476
829517d4 477Example:
f017c022 478
829517d4 479 package My::Schema;
480 use base qw/DBIx::Class::Schema/;
481 use My::ExceptionClass;
482 __PACKAGE__->exception_action(sub { My::ExceptionClass->throw(@_) });
483 __PACKAGE__->load_classes;
2374c5ff 484
829517d4 485 # or:
486 my $schema_obj = My::Schema->connect( .... );
487 $schema_obj->exception_action(sub { My::ExceptionClass->throw(@_) });
0f4ec1d2 488
829517d4 489=head2 stacktrace
f017c022 490
829517d4 491=over 4
2374c5ff 492
829517d4 493=item Arguments: boolean
2374c5ff 494
829517d4 495=back
2374c5ff 496
829517d4 497Whether L</throw_exception> should include stack trace information.
498Defaults to false normally, but defaults to true if C<$ENV{DBIC_TRACE}>
499is true.
0f4ec1d2 500
829517d4 501=head2 sqlt_deploy_hook
0f4ec1d2 502
829517d4 503=over
0f4ec1d2 504
829517d4 505=item Arguments: $sqlt_schema
2374c5ff 506
829517d4 507=back
2374c5ff 508
fd323bf1 509An optional sub which you can declare in your own Schema class that will get
829517d4 510passed the L<SQL::Translator::Schema> object when you deploy the schema via
511L</create_ddl_dir> or L</deploy>.
0f4ec1d2 512
fd323bf1 513For an example of what you can do with this, see
829517d4 514L<DBIx::Class::Manual::Cookbook/Adding Indexes And Functions To Your SQL>.
fdcd8145 515
2d7d8459 516Note that sqlt_deploy_hook is called by L</deployment_statements>, which in turn
517is called before L</deploy>. Therefore the hook can be used only to manipulate
518the L<SQL::Translator::Schema> object before it is turned into SQL fed to the
519database. If you want to execute post-deploy statements which can not be generated
520by L<SQL::Translator>, the currently suggested method is to overload L</deploy>
521and use L<dbh_do|DBIx::Class::Storage::DBI/dbh_do>.
522
829517d4 523=head1 METHODS
2374c5ff 524
829517d4 525=head2 connect
87c4e602 526
27f01d1f 527=over 4
528
829517d4 529=item Arguments: @connectinfo
429bd4f1 530
d601dc88 531=item Return Value: $new_schema
27f01d1f 532
533=back
076652e8 534
829517d4 535Creates and returns a new Schema object. The connection info set on it
536is used to create a new instance of the storage backend and set it on
537the Schema object.
1c133e22 538
829517d4 539See L<DBIx::Class::Storage::DBI/"connect_info"> for DBI-specific
5d52945a 540syntax on the C<@connectinfo> argument, or L<DBIx::Class::Storage> in
829517d4 541general.
1c133e22 542
5d52945a 543Note that C<connect_info> expects an arrayref of arguments, but
faaba25f 544C<connect> does not. C<connect> wraps its arguments in an arrayref
5d52945a 545before passing them to C<connect_info>.
546
4c7d99ca 547=head3 Overloading
548
549C<connect> is a convenience method. It is equivalent to calling
550$schema->clone->connection(@connectinfo). To write your own overloaded
551version, overload L</connection> instead.
552
076652e8 553=cut
554
e5053694 555sub connect {
556 DBIx::Class::_ENV_::ASSERT_NO_INTERNAL_INDIRECT_CALLS and fail_on_internal_call;
557 shift->clone->connection(@_);
558}
e678398e 559
829517d4 560=head2 resultset
77254782 561
27f01d1f 562=over 4
563
fb13a49f 564=item Arguments: L<$source_name|DBIx::Class::ResultSource/source_name>
82b01c38 565
fb13a49f 566=item Return Value: L<$resultset|DBIx::Class::ResultSet>
27f01d1f 567
568=back
13765dad 569
829517d4 570 my $rs = $schema->resultset('DVD');
82b01c38 571
829517d4 572Returns the L<DBIx::Class::ResultSet> object for the registered source
573name.
77254782 574
575=cut
576
829517d4 577sub resultset {
fb13a49f 578 my ($self, $source_name) = @_;
73d47f9f 579 $self->throw_exception('resultset() expects a source name')
fb13a49f 580 unless defined $source_name;
581 return $self->source($source_name)->resultset;
b7951443 582}
583
829517d4 584=head2 sources
6b43ba5f 585
586=over 4
587
fb13a49f 588=item Return Value: L<@source_names|DBIx::Class::ResultSource/source_name>
6b43ba5f 589
590=back
591
829517d4 592 my @source_names = $schema->sources;
6b43ba5f 593
829517d4 594Lists names of all the sources registered on this Schema object.
6b43ba5f 595
829517d4 596=cut
161fb223 597
93d7452f 598sub sources { keys %{shift->source_registrations} }
106d5f3b 599
829517d4 600=head2 source
87c4e602 601
27f01d1f 602=over 4
603
fb13a49f 604=item Arguments: L<$source_name|DBIx::Class::ResultSource/source_name>
66d9ef6b 605
fb13a49f 606=item Return Value: L<$result_source|DBIx::Class::ResultSource>
27f01d1f 607
608=back
82b01c38 609
829517d4 610 my $source = $schema->source('Book');
85f78622 611
829517d4 612Returns the L<DBIx::Class::ResultSource> object for the registered
613source name.
66d9ef6b 614
615=cut
616
829517d4 617sub source {
d46eac43 618 my ($self, $source_name) = @_;
f5f2af8f 619
620 $self->throw_exception("source() expects a source name")
d46eac43 621 unless $source_name;
f5f2af8f 622
d46eac43 623 my $source_registrations;
829517d4 624
d46eac43 625 my $rsrc =
626 ( $source_registrations = $self->source_registrations )->{$source_name}
627 ||
628 # if we got here, they probably passed a full class name
629 $source_registrations->{ $self->class_mappings->{$source_name} || '' }
630 ||
631 $self->throw_exception( "Can't find source for ${source_name}" )
632 ;
7648acb5 633
634 # DO NOT REMOVE:
635 # We need to prevent alterations of pre-existing $@ due to where this call
636 # sits in the overall stack ( *unless* of course there is an actual error
637 # to report ). set_mro does alter $@ (and yes - it *can* throw an exception)
638 # We do not use local because set_mro *can* throw an actual exception
639 # We do not use a try/catch either, as on one hand it would slow things
640 # down for no reason (we would always rethrow), but also because adding *any*
641 # try/catch block below will segfault various threading tests on older perls
642 # ( which in itself is a FIXME but ENOTIMETODIG )
643 my $old_dollarat = $@;
644
645 no strict 'refs';
646 mro::set_mro($_, 'c3') for
647 grep
648 {
649 # some pseudo-sources do not have a result/resultset yet
650 defined $_
651 and
652 (
653 (
654 ${"${_}::__INITIAL_MRO_UPON_DBIC_LOAD__"}
655 ||= mro::get_mro($_)
656 )
657 ne
658 'c3'
659 )
660 }
661 map
662 { length ref $_ ? ref $_ : $_ }
663 ( $rsrc, $rsrc->result_class, $rsrc->resultset_class )
664 ;
665
666 # DO NOT REMOVE - see comment above
667 $@ = $old_dollarat;
668
669 $rsrc;
161fb223 670}
671
829517d4 672=head2 class
87c4e602 673
27f01d1f 674=over 4
675
fb13a49f 676=item Arguments: L<$source_name|DBIx::Class::ResultSource/source_name>
66d9ef6b 677
829517d4 678=item Return Value: $classname
27f01d1f 679
680=back
82b01c38 681
829517d4 682 my $class = $schema->class('CD');
683
684Retrieves the Result class name for the given source name.
66d9ef6b 685
686=cut
687
829517d4 688sub class {
4b8a53ea 689 return shift->source(shift)->result_class;
829517d4 690}
08b515f1 691
4012acd8 692=head2 txn_do
08b515f1 693
4012acd8 694=over 4
08b515f1 695
4012acd8 696=item Arguments: C<$coderef>, @coderef_args?
08b515f1 697
4012acd8 698=item Return Value: The return value of $coderef
08b515f1 699
4012acd8 700=back
08b515f1 701
4012acd8 702Executes C<$coderef> with (optional) arguments C<@coderef_args> atomically,
703returning its result (if any). Equivalent to calling $schema->storage->txn_do.
704See L<DBIx::Class::Storage/"txn_do"> for more information.
08b515f1 705
4012acd8 706This interface is preferred over using the individual methods L</txn_begin>,
707L</txn_commit>, and L</txn_rollback> below.
08b515f1 708
f9f06ae0 709WARNING: If you are connected with C<< AutoCommit => 0 >> the transaction is
281719d2 710considered nested, and you will still need to call L</txn_commit> to write your
f9f06ae0 711changes when appropriate. You will also want to connect with C<< auto_savepoint =>
7121 >> to get partial rollback to work, if the storage driver for your database
281719d2 713supports it.
714
f9f06ae0 715Connecting with C<< AutoCommit => 1 >> is recommended.
281719d2 716
4012acd8 717=cut
08b515f1 718
4012acd8 719sub txn_do {
720 my $self = shift;
08b515f1 721
4012acd8 722 $self->storage or $self->throw_exception
723 ('txn_do called on $schema without storage');
08b515f1 724
4012acd8 725 $self->storage->txn_do(@_);
726}
66d9ef6b 727
6936e902 728=head2 txn_scope_guard
75c8a7ab 729
fd323bf1 730Runs C<txn_scope_guard> on the schema's storage. See
89028f42 731L<DBIx::Class::Storage/txn_scope_guard>.
75c8a7ab 732
b85be4c1 733=cut
734
1bc193ac 735sub txn_scope_guard {
736 my $self = shift;
737
738 $self->storage or $self->throw_exception
739 ('txn_scope_guard called on $schema without storage');
740
741 $self->storage->txn_scope_guard(@_);
742}
743
4012acd8 744=head2 txn_begin
a62cf8d4 745
4012acd8 746Begins a transaction (does nothing if AutoCommit is off). Equivalent to
747calling $schema->storage->txn_begin. See
8bfce9d5 748L<DBIx::Class::Storage/"txn_begin"> for more information.
27f01d1f 749
4012acd8 750=cut
82b01c38 751
4012acd8 752sub txn_begin {
753 my $self = shift;
27f01d1f 754
4012acd8 755 $self->storage or $self->throw_exception
756 ('txn_begin called on $schema without storage');
a62cf8d4 757
4012acd8 758 $self->storage->txn_begin;
759}
a62cf8d4 760
4012acd8 761=head2 txn_commit
a62cf8d4 762
4012acd8 763Commits the current transaction. Equivalent to calling
8bfce9d5 764$schema->storage->txn_commit. See L<DBIx::Class::Storage/"txn_commit">
4012acd8 765for more information.
a62cf8d4 766
4012acd8 767=cut
a62cf8d4 768
4012acd8 769sub txn_commit {
770 my $self = shift;
a62cf8d4 771
4012acd8 772 $self->storage or $self->throw_exception
773 ('txn_commit called on $schema without storage');
a62cf8d4 774
4012acd8 775 $self->storage->txn_commit;
776}
70634260 777
4012acd8 778=head2 txn_rollback
a62cf8d4 779
4012acd8 780Rolls back the current transaction. Equivalent to calling
781$schema->storage->txn_rollback. See
8bfce9d5 782L<DBIx::Class::Storage/"txn_rollback"> for more information.
a62cf8d4 783
784=cut
785
4012acd8 786sub txn_rollback {
787 my $self = shift;
a62cf8d4 788
19630353 789 $self->storage or $self->throw_exception
4012acd8 790 ('txn_rollback called on $schema without storage');
a62cf8d4 791
4012acd8 792 $self->storage->txn_rollback;
a62cf8d4 793}
794
829517d4 795=head2 storage
66d9ef6b 796
829517d4 797 my $storage = $schema->storage;
04786a4c 798
829517d4 799Returns the L<DBIx::Class::Storage> object for this Schema. Grab this
800if you want to turn on SQL statement debugging at runtime, or set the
801quote character. For the default storage, the documentation can be
802found in L<DBIx::Class::Storage::DBI>.
66d9ef6b 803
87c4e602 804=head2 populate
805
27f01d1f 806=over 4
807
44e95db4 808=item Arguments: L<$source_name|DBIx::Class::ResultSource/source_name>, [ \@column_list, \@row_values+ ] | [ \%col_data+ ]
27f01d1f 809
44e95db4 810=item Return Value: L<\@result_objects|DBIx::Class::Manual::ResultClass> (scalar context) | L<@result_objects|DBIx::Class::Manual::ResultClass> (list context)
829517d4 811
27f01d1f 812=back
a37a4697 813
44e95db4 814A convenience shortcut to L<DBIx::Class::ResultSet/populate>. Equivalent to:
815
816 $schema->resultset($source_name)->populate([...]);
817
818=over 4
819
820=item NOTE
821
822The context of this method call has an important effect on what is
823submitted to storage. In void context data is fed directly to fastpath
824insertion routines provided by the underlying storage (most often
825L<DBI/execute_for_fetch>), bypassing the L<new|DBIx::Class::Row/new> and
826L<insert|DBIx::Class::Row/insert> calls on the
827L<Result|DBIx::Class::Manual::ResultClass> class, including any
828augmentation of these methods provided by components. For example if you
829are using something like L<DBIx::Class::UUIDColumns> to create primary
830keys for you, you will find that your PKs are empty. In this case you
831will have to explicitly force scalar or list context in order to create
832those values.
833
834=back
a37a4697 835
836=cut
837
838sub populate {
e5053694 839 DBIx::Class::_ENV_::ASSERT_NO_INTERNAL_INDIRECT_CALLS and fail_on_internal_call;
840
a37a4697 841 my ($self, $name, $data) = @_;
4b8a53ea 842 my $rs = $self->resultset($name)
843 or $self->throw_exception("'$name' is not a resultset");
844
845 return $rs->populate($data);
a37a4697 846}
847
829517d4 848=head2 connection
849
850=over 4
851
852=item Arguments: @args
853
759a7f44 854=item Return Value: $self
829517d4 855
856=back
857
858Similar to L</connect> except sets the storage object and connection
759a7f44 859data B<in-place> on C<$self>. You should probably be calling
860L</connect> to get a properly L<cloned|/clone> Schema object instead.
829517d4 861
4c7d99ca 862=head3 Overloading
863
864Overload C<connection> to change the behaviour of C<connect>.
829517d4 865
866=cut
867
868sub connection {
869 my ($self, @info) = @_;
870 return $self if !@info && $self->storage;
d4daee7b 871
93d7452f 872 my ($storage_class, $args) = ref $self->storage_type
873 ? $self->_normalize_storage_type($self->storage_type)
874 : $self->storage_type
875 ;
876
877 $storage_class =~ s/^::/DBIx::Class::Storage::/;
d4daee7b 878
ddcc02d1 879 dbic_internal_try {
9780718f 880 $self->ensure_class_loaded ($storage_class);
881 }
882 catch {
883 $self->throw_exception(
dee99c24 884 "Unable to load storage class ${storage_class}: $_"
9780718f 885 );
886 };
93d7452f 887
888 my $storage = $storage_class->new( $self => $args||{} );
829517d4 889 $storage->connect_info(\@info);
890 $self->storage($storage);
891 return $self;
892}
893
894sub _normalize_storage_type {
895 my ($self, $storage_type) = @_;
896 if(ref $storage_type eq 'ARRAY') {
897 return @$storage_type;
898 } elsif(ref $storage_type eq 'HASH') {
899 return %$storage_type;
900 } else {
901 $self->throw_exception('Unsupported REFTYPE given: '. ref $storage_type);
902 }
903}
904
905=head2 compose_namespace
82cc0386 906
907=over 4
908
829517d4 909=item Arguments: $target_namespace, $additional_base_class?
910
8600b1c1 911=item Return Value: $new_schema
829517d4 912
913=back
914
915For each L<DBIx::Class::ResultSource> in the schema, this method creates a
916class in the target namespace (e.g. $target_namespace::CD,
917$target_namespace::Artist) that inherits from the corresponding classes
918attached to the current schema.
919
920It also attaches a corresponding L<DBIx::Class::ResultSource> object to the
921new $schema object. If C<$additional_base_class> is given, the new composed
48580715 922classes will inherit from first the corresponding class from the current
829517d4 923schema then the base class.
924
925For example, for a schema with My::Schema::CD and My::Schema::Artist classes,
926
927 $schema->compose_namespace('My::DB', 'Base::Class');
928 print join (', ', @My::DB::CD::ISA) . "\n";
929 print join (', ', @My::DB::Artist::ISA) ."\n";
930
931will produce the output
932
933 My::Schema::CD, Base::Class
934 My::Schema::Artist, Base::Class
935
936=cut
937
829517d4 938sub compose_namespace {
939 my ($self, $target, $base) = @_;
dee99c24 940
829517d4 941 my $schema = $self->clone;
dee99c24 942
943 $schema->source_registrations({});
944
945 # the original class-mappings must remain - otherwise
946 # reverse_relationship_info will not work
947 #$schema->class_mappings({});
948
829517d4 949 {
950 no warnings qw/redefine/;
87bf71d5 951 local *Class::C3::reinitialize = sub { } if DBIx::Class::_ENV_::OLD_MRO;
952 use warnings qw/redefine/;
953
fb13a49f 954 foreach my $source_name ($self->sources) {
955 my $orig_source = $self->source($source_name);
dee99c24 956
fb13a49f 957 my $target_class = "${target}::${source_name}";
dee99c24 958 $self->inject_base($target_class, $orig_source->result_class, ($base || ()) );
959
534aff61 960 $schema->register_source(
961 $source_name,
962 $orig_source->clone(
963 result_class => $target_class
964 ),
829517d4 965 );
829517d4 966 }
dee99c24 967
d99f2db7 968 # Legacy stuff, not inserting INDIRECT assertions
8d73fcd4 969 quote_sub "${target}::${_}" => "shift->schema->$_(\@_)"
970 for qw(class source resultset);
829517d4 971 }
dee99c24 972
973 Class::C3->reinitialize() if DBIx::Class::_ENV_::OLD_MRO;
974
534aff61 975 # Give each composed class yet another *schema-less* source copy
976 # this is used for the freeze/thaw cycle
977 #
978 # This is not covered by any tests directly, but is indirectly exercised
979 # in t/cdbi/sweet/08pager by re-setting the schema on an existing object
980 # FIXME - there is likely a much cheaper way to take care of this
981 for my $source_name ($self->sources) {
982
983 my $target_class = "${target}::${source_name}";
984
985 $target_class->result_source_instance(
986 $self->source($source_name)->clone(
987 result_class => $target_class,
988 schema => ( ref $schema || $schema ),
989 )
990 );
991 }
992
829517d4 993 return $schema;
994}
995
759a7f44 996# LEGACY: The intra-call to this was removed in 66d9ef6b and then
997# the sub was de-documented way later in 249963d4. No way to be sure
998# nothing on darkpan is calling it directly, so keeping as-is
829517d4 999sub setup_connection_class {
1000 my ($class, $target, @info) = @_;
1001 $class->inject_base($target => 'DBIx::Class::DB');
1002 #$target->load_components('DB');
1003 $target->connection(@info);
1004}
1005
1006=head2 svp_begin
1007
fd323bf1 1008Creates a new savepoint (does nothing outside a transaction).
829517d4 1009Equivalent to calling $schema->storage->svp_begin. See
8bfce9d5 1010L<DBIx::Class::Storage/"svp_begin"> for more information.
829517d4 1011
1012=cut
1013
1014sub svp_begin {
1015 my ($self, $name) = @_;
1016
1017 $self->storage or $self->throw_exception
1018 ('svp_begin called on $schema without storage');
1019
1020 $self->storage->svp_begin($name);
1021}
1022
1023=head2 svp_release
1024
fd323bf1 1025Releases a savepoint (does nothing outside a transaction).
829517d4 1026Equivalent to calling $schema->storage->svp_release. See
8bfce9d5 1027L<DBIx::Class::Storage/"svp_release"> for more information.
829517d4 1028
1029=cut
1030
1031sub svp_release {
1032 my ($self, $name) = @_;
1033
1034 $self->storage or $self->throw_exception
1035 ('svp_release called on $schema without storage');
82cc0386 1036
829517d4 1037 $self->storage->svp_release($name);
1038}
82cc0386 1039
829517d4 1040=head2 svp_rollback
db5dc233 1041
fd323bf1 1042Rollback to a savepoint (does nothing outside a transaction).
829517d4 1043Equivalent to calling $schema->storage->svp_rollback. See
8bfce9d5 1044L<DBIx::Class::Storage/"svp_rollback"> for more information.
82cc0386 1045
829517d4 1046=cut
82cc0386 1047
829517d4 1048sub svp_rollback {
1049 my ($self, $name) = @_;
82cc0386 1050
829517d4 1051 $self->storage or $self->throw_exception
1052 ('svp_rollback called on $schema without storage');
82cc0386 1053
829517d4 1054 $self->storage->svp_rollback($name);
1055}
db5dc233 1056
829517d4 1057=head2 clone
613397e7 1058
84c5863b 1059=over 4
613397e7 1060
71829446 1061=item Arguments: %attrs?
1062
829517d4 1063=item Return Value: $new_schema
613397e7 1064
1065=back
1066
829517d4 1067Clones the schema and its associated result_source objects and returns the
71829446 1068copy. The resulting copy will have the same attributes as the source schema,
4a0eed52 1069except for those attributes explicitly overridden by the provided C<%attrs>.
829517d4 1070
1071=cut
1072
1073sub clone {
71829446 1074 my $self = shift;
1075
1076 my $clone = {
1077 (ref $self ? %$self : ()),
1078 (@_ == 1 && ref $_[0] eq 'HASH' ? %{ $_[0] } : @_),
1079 };
829517d4 1080 bless $clone, (ref $self || $self);
1081
93963f59 1082 $clone->$_(undef) for qw/class_mappings source_registrations storage/;
1083
1084 $clone->_copy_state_from($self);
1085
1086 return $clone;
1087}
1088
1089# Needed in Schema::Loader - if you refactor, please make a compatibility shim
1090# -- Caelum
1091sub _copy_state_from {
1092 my ($self, $from) = @_;
1093
1094 $self->class_mappings({ %{$from->class_mappings} });
1095 $self->source_registrations({ %{$from->source_registrations} });
1096
534aff61 1097 # we use extra here as we want to leave the class_mappings as they are
1098 # but overwrite the source_registrations entry with the new source
1099 $self->register_extra_source( $_ => $from->source($_) )
1100 for $from->sources;
dee99c24 1101
93963f59 1102 if ($from->storage) {
1103 $self->storage($from->storage);
1104 $self->storage->set_schema($self);
1105 }
829517d4 1106}
613397e7 1107
5160b401 1108=head2 throw_exception
701da8c4 1109
75d07914 1110=over 4
82b01c38 1111
ebc77b53 1112=item Arguments: $message
82b01c38 1113
1114=back
1115
70c28808 1116Throws an exception. Obeys the exemption rules of L<DBIx::Class::Carp> to report
1117errors from outer-user's perspective. See L</exception_action> for details on overriding
4b946902 1118this method's behavior. If L</stacktrace> is turned on, C<throw_exception>'s
1119default behavior will provide a detailed stack trace.
701da8c4 1120
1121=cut
1122
1123sub throw_exception {
e240b8ba 1124 my ($self, @args) = @_;
4981dc70 1125
ddcc02d1 1126 if (
1127 ! DBIx::Class::_Util::in_internal_try()
1128 and
1129 my $act = $self->exception_action
1130 ) {
7cb35852 1131
1132 my $guard_disarmed;
1133
1134 my $guard = scope_guard {
1135 return if $guard_disarmed;
c40b5744 1136 emit_loud_diag( emit_dups => 1, msg => "
1137
7cb35852 1138 !!! DBIx::Class INTERNAL PANIC !!!
1139
1140The exception_action() handler installed on '$self'
1141aborted the stacktrace below via a longjmp (either via Return::Multilevel or
1142plain goto, or Scope::Upper or something equally nefarious). There currently
1143is nothing safe DBIx::Class can do, aside from displaying this error. A future
1144version ( 0.082900, when available ) will reduce the cases in which the
1145handler is invoked, but this is neither a complete solution, nor can it do
1146anything for other software that might be affected by a similar problem.
1147
1148 !!! FIX YOUR ERROR HANDLING !!!
1149
c40b5744 1150This guard was activated starting",
7cb35852 1151 );
1152 };
1153
7704dbc9 1154 dbic_internal_try {
118b2c36 1155 # if it throws - good, we'll assign to @args in the end
e240b8ba 1156 # if it doesn't - do different things depending on RV truthiness
1157 if( $act->(@args) ) {
1158 $args[0] = (
c3e9f718 1159 "Invocation of the exception_action handler installed on $self did *not*"
1160 .' result in an exception. DBIx::Class is unable to function without a reliable'
118b2c36 1161 .' exception mechanism, ensure your exception_action does not hide exceptions'
e240b8ba 1162 ." (original error: $args[0])"
1163 );
1164 }
1165 else {
1166 carp_unique (
1167 "The exception_action handler installed on $self returned false instead"
1168 .' of throwing an exception. This behavior has been deprecated, adjust your'
7cb35852 1169 .' handler to always rethrow the supplied error'
e240b8ba 1170 );
1171 }
7cb35852 1172
118b2c36 1173 1;
7cb35852 1174 }
7704dbc9 1175 catch {
1176 # We call this to get the necessary warnings emitted and disregard the RV
1177 # as it's definitely an exception if we got as far as this catch{} block
1178 is_exception(
1179 $args[0] = $_
1180 );
1181 };
f9080e45 1182
118b2c36 1183 # Done guarding against https://github.com/PerlDancer/Dancer2/issues/1125
1184 $guard_disarmed = 1;
c3e9f718 1185 }
1186
e240b8ba 1187 DBIx::Class::Exception->throw( $args[0], $self->stacktrace );
701da8c4 1188}
1189
dfccde48 1190=head2 deploy
1c339d71 1191
82b01c38 1192=over 4
1193
10976519 1194=item Arguments: \%sqlt_args, $dir
82b01c38 1195
1196=back
1197
1198Attempts to deploy the schema to the current storage using L<SQL::Translator>.
ec6704d4 1199
10976519 1200See L<SQL::Translator/METHODS> for a list of values for C<\%sqlt_args>.
1201The most common value for this would be C<< { add_drop_table => 1 } >>
1202to have the SQL produced include a C<DROP TABLE> statement for each table
b5d783cd 1203created. For quoting purposes supply C<quote_identifiers>.
51bace1c 1204
fd323bf1 1205Additionally, the DBIx::Class parser accepts a C<sources> parameter as a hash
1206ref or an array ref, containing a list of source to deploy. If present, then
0e2c6809 1207only the sources listed will get deployed. Furthermore, you can use the
1208C<add_fk_index> parser parameter to prevent the parser from creating an index for each
1209FK.
499adf63 1210
1c339d71 1211=cut
1212
1213sub deploy {
6e73ac25 1214 my ($self, $sqltargs, $dir) = @_;
1c339d71 1215 $self->throw_exception("Can't deploy without storage") unless $self->storage;
6e73ac25 1216 $self->storage->deploy($self, undef, $sqltargs, $dir);
1c339d71 1217}
1218
0e0ce6c1 1219=head2 deployment_statements
1220
1221=over 4
1222
10976519 1223=item Arguments: See L<DBIx::Class::Storage::DBI/deployment_statements>
0e0ce6c1 1224
fb13a49f 1225=item Return Value: $listofstatements
829517d4 1226
0e0ce6c1 1227=back
1228
10976519 1229A convenient shortcut to
1230C<< $self->storage->deployment_statements($self, @args) >>.
5529838f 1231Returns the statements used by L</deploy> and
1232L<DBIx::Class::Storage/deploy>.
0e0ce6c1 1233
1234=cut
1235
1236sub deployment_statements {
7ad93f5a 1237 my $self = shift;
0e0ce6c1 1238
1239 $self->throw_exception("Can't generate deployment statements without a storage")
1240 if not $self->storage;
1241
7ad93f5a 1242 $self->storage->deployment_statements($self, @_);
0e0ce6c1 1243}
1244
6dfbe2f8 1245=head2 create_ddl_dir
c0f61310 1246
1247=over 4
1248
10976519 1249=item Arguments: See L<DBIx::Class::Storage::DBI/create_ddl_dir>
c0f61310 1250
1251=back
1252
fd323bf1 1253A convenient shortcut to
10976519 1254C<< $self->storage->create_ddl_dir($self, @args) >>.
c9d2e0a2 1255
10976519 1256Creates an SQL file based on the Schema, for each of the specified
1257database types, in the given directory.
c9d2e0a2 1258
c0f61310 1259=cut
1260
6e73ac25 1261sub create_ddl_dir {
e673f011 1262 my $self = shift;
1263
1264 $self->throw_exception("Can't create_ddl_dir without storage") unless $self->storage;
1265 $self->storage->create_ddl_dir($self, @_);
1266}
1267
e63a82f7 1268=head2 ddl_filename
9b83fccd 1269
c9d2e0a2 1270=over 4
1271
99a74c4a 1272=item Arguments: $database-type, $version, $directory, $preversion
c9d2e0a2 1273
fb13a49f 1274=item Return Value: $normalised_filename
829517d4 1275
c9d2e0a2 1276=back
1277
99a74c4a 1278 my $filename = $table->ddl_filename($type, $version, $dir, $preversion)
c9d2e0a2 1279
1280This method is called by C<create_ddl_dir> to compose a file name out of
1281the supplied directory, database type and version number. The default file
1282name format is: C<$dir$schema-$version-$type.sql>.
9b83fccd 1283
c9d2e0a2 1284You may override this method in your schema if you wish to use a different
1285format.
9b83fccd 1286
1acfef8e 1287 WARNING
1288
1289 Prior to DBIx::Class version 0.08100 this method had a different signature:
1290
1291 my $filename = $table->ddl_filename($type, $dir, $version, $preversion)
1292
1293 In recent versions variables $dir and $version were reversed in order to
fd323bf1 1294 bring the signature in line with other Schema/Storage methods. If you
1acfef8e 1295 really need to maintain backward compatibility, you can do the following
1296 in any overriding methods:
1297
1298 ($dir, $version) = ($version, $dir) if ($DBIx::Class::VERSION < 0.08100);
1299
9b83fccd 1300=cut
1301
6e73ac25 1302sub ddl_filename {
99a74c4a 1303 my ($self, $type, $version, $dir, $preversion) = @_;
e673f011 1304
aea59b74 1305 $version = "$preversion-$version" if $preversion;
d4daee7b 1306
aea59b74 1307 my $class = blessed($self) || $self;
1308 $class =~ s/::/-/g;
1309
aff5e9c1 1310 return "$dir/$class-$version-$type.sql";
e673f011 1311}
1312
4146e3da 1313=head2 thaw
1314
fd323bf1 1315Provided as the recommended way of thawing schema objects. You can call
4146e3da 1316C<Storable::thaw> directly if you wish, but the thawed objects will not have a
48580715 1317reference to any schema, so are rather useless.
4146e3da 1318
1319=cut
1320
1321sub thaw {
1322 my ($self, $obj) = @_;
1323 local $DBIx::Class::ResultSourceHandle::thaw_schema = $self;
1324 return Storable::thaw($obj);
1325}
1326
1327=head2 freeze
1328
5529838f 1329This doesn't actually do anything beyond calling L<nfreeze|Storable/SYNOPSIS>,
1330it is just provided here for symmetry.
4146e3da 1331
d2f3e87b 1332=cut
1333
4146e3da 1334sub freeze {
26148d36 1335 return Storable::nfreeze($_[1]);
4146e3da 1336}
1337
1338=head2 dclone
1339
1477a478 1340=over 4
1341
1342=item Arguments: $object
1343
1344=item Return Value: dcloned $object
1345
1346=back
1347
9e9ecfda 1348Recommended way of dcloning L<DBIx::Class::Row> and L<DBIx::Class::ResultSet>
1349objects so their references to the schema object
1350(which itself is B<not> cloned) are properly maintained.
4146e3da 1351
1352=cut
1353
1354sub dclone {
1355 my ($self, $obj) = @_;
1356 local $DBIx::Class::ResultSourceHandle::thaw_schema = $self;
1357 return Storable::dclone($obj);
1358}
1359
93e4d41a 1360=head2 schema_version
1361
829517d4 1362Returns the current schema class' $VERSION in a normalised way.
93e4d41a 1363
1364=cut
1365
1366sub schema_version {
1367 my ($self) = @_;
1368 my $class = ref($self)||$self;
1369
1370 # does -not- use $schema->VERSION
1371 # since that varies in results depending on if version.pm is installed, and if
1372 # so the perl or XS versions. If you want this to change, bug the version.pm
1373 # author to make vpp and vxs behave the same.
1374
1375 my $version;
1376 {
1377 no strict 'refs';
1378 $version = ${"${class}::VERSION"};
1379 }
1380 return $version;
1381}
1382
829517d4 1383
1384=head2 register_class
1385
1386=over 4
1387
fb13a49f 1388=item Arguments: $source_name, $component_class
829517d4 1389
1390=back
1391
fd323bf1 1392This method is called by L</load_namespaces> and L</load_classes> to install the found classes into your Schema. You should be using those instead of this one.
829517d4 1393
1394You will only need this method if you have your Result classes in
1395files which are not named after the packages (or all in the same
1396file). You may also need it to register classes at runtime.
1397
1398Registers a class which isa DBIx::Class::ResultSourceProxy. Equivalent to
1399calling:
1400
fb13a49f 1401 $schema->register_source($source_name, $component_class->result_source_instance);
829517d4 1402
1403=cut
1404
1405sub register_class {
fb13a49f 1406 my ($self, $source_name, $to_register) = @_;
1407 $self->register_source($source_name => $to_register->result_source_instance);
829517d4 1408}
1409
1410=head2 register_source
1411
1412=over 4
1413
fb13a49f 1414=item Arguments: $source_name, L<$result_source|DBIx::Class::ResultSource>
829517d4 1415
1416=back
1417
1418This method is called by L</register_class>.
1419
1420Registers the L<DBIx::Class::ResultSource> in the schema with the given
fb13a49f 1421source name.
829517d4 1422
1423=cut
1424
dee99c24 1425sub register_source { shift->_register_source(@_) }
829517d4 1426
98cabed3 1427=head2 unregister_source
1428
1429=over 4
1430
fb13a49f 1431=item Arguments: $source_name
98cabed3 1432
1433=back
1434
fb13a49f 1435Removes the L<DBIx::Class::ResultSource> from the schema for the given source name.
98cabed3 1436
1437=cut
1438
dee99c24 1439sub unregister_source { shift->_unregister_source(@_) }
98cabed3 1440
829517d4 1441=head2 register_extra_source
1442
1443=over 4
1444
fb13a49f 1445=item Arguments: $source_name, L<$result_source|DBIx::Class::ResultSource>
829517d4 1446
1447=back
1448
fd323bf1 1449As L</register_source> but should be used if the result class already
829517d4 1450has a source and you want to register an extra one.
1451
1452=cut
1453
dee99c24 1454sub register_extra_source { shift->_register_source(@_, { extra => 1 }) }
829517d4 1455
1456sub _register_source {
d46eac43 1457 my ($self, $source_name, $supplied_rsrc, $params) = @_;
1458
534aff61 1459 my $derived_rsrc = $supplied_rsrc->clone({
d46eac43 1460 source_name => $source_name,
1461 });
829517d4 1462
d46eac43 1463 # Do not move into the clone-hashref above: there are things
1464 # on CPAN that do hook 'sub schema' </facepalm>
1465 # https://metacpan.org/source/LSAUNDERS/DBIx-Class-Preview-1.000003/lib/DBIx/Class/ResultSource/Table/Previewed.pm#L9-38
1466 $derived_rsrc->schema($self);
dee99c24 1467
d46eac43 1468 weaken $derived_rsrc->{schema}
1469 if length ref($self);
2461ae19 1470
829517d4 1471 my %reg = %{$self->source_registrations};
d46eac43 1472 $reg{$source_name} = $derived_rsrc;
829517d4 1473 $self->source_registrations(\%reg);
1474
d46eac43 1475 return $derived_rsrc if $params->{extra};
dee99c24 1476
d46eac43 1477 my( $result_class, $result_class_level_rsrc );
1478 if (
1479 $result_class = $derived_rsrc->result_class
1480 and
1481 # There are known cases where $rs_class is *ONLY* an inflator, without
1482 # any hint of a rsrc (e.g. DBIx::Class::KiokuDB::EntryProxy)
1483 $result_class_level_rsrc = dbic_internal_try { $result_class->result_source_instance }
1484 ) {
dee99c24 1485 my %map = %{$self->class_mappings};
d46eac43 1486
1487 carp (
1488 "$result_class already had a registered source which was replaced by "
1489 . 'this call. Perhaps you wanted register_extra_source(), though it is '
1490 . 'more likely you did something wrong.'
1491 ) if (
1492 exists $map{$result_class}
dee99c24 1493 and
d46eac43 1494 $map{$result_class} ne $source_name
dee99c24 1495 and
d46eac43 1496 $result_class_level_rsrc != $supplied_rsrc
1497 );
dee99c24 1498
d46eac43 1499 $map{$result_class} = $source_name;
dee99c24 1500 $self->class_mappings(\%map);
829517d4 1501 }
dee99c24 1502
d46eac43 1503 $derived_rsrc;
829517d4 1504}
1505
a4367b26 1506my $global_phase_destroy;
1507sub DESTROY {
e1d9e578 1508 ### NO detected_reinvoked_destructor check
3d56e026 1509 ### This code very much relies on being called multuple times
1510
a4367b26 1511 return if $global_phase_destroy ||= in_global_destruction;
66917da3 1512
a4367b26 1513 my $self = shift;
1514 my $srcs = $self->source_registrations;
1515
fb13a49f 1516 for my $source_name (keys %$srcs) {
a4367b26 1517 # find first source that is not about to be GCed (someone other than $self
1518 # holds a reference to it) and reattach to it, weakening our own link
1519 #
1520 # during global destruction (if we have not yet bailed out) this should throw
1521 # which will serve as a signal to not try doing anything else
1522 # however beware - on older perls the exception seems randomly untrappable
1523 # due to some weird race condition during thread joining :(((
dac7972a 1524 if (length ref $srcs->{$source_name} and refcount($srcs->{$source_name}) > 1) {
5c33c8be 1525 local $SIG{__DIE__} if $SIG{__DIE__};
7db939de 1526 local $@ if DBIx::Class::_ENV_::UNSTABLE_DOLLARAT;
a4367b26 1527 eval {
fb13a49f 1528 $srcs->{$source_name}->schema($self);
1529 weaken $srcs->{$source_name};
a4367b26 1530 1;
1531 } or do {
1532 $global_phase_destroy = 1;
1533 };
1534
1535 last;
50261284 1536 }
1537 }
d52fc26d 1538
1539 # Dummy NEXTSTATE ensuring the all temporaries on the stack are garbage
1540 # collected before leaving this scope. Depending on the code above, this
1541 # may very well be just a preventive measure guarding future modifications
1542 undef;
50261284 1543}
1544
829517d4 1545sub _unregister_source {
fb13a49f 1546 my ($self, $source_name) = @_;
fd323bf1 1547 my %reg = %{$self->source_registrations};
829517d4 1548
fb13a49f 1549 my $source = delete $reg{$source_name};
829517d4 1550 $self->source_registrations(\%reg);
1551 if ($source->result_class) {
1552 my %map = %{$self->class_mappings};
1553 delete $map{$source->result_class};
1554 $self->class_mappings(\%map);
1555 }
1556}
1557
1558
1559=head2 compose_connection (DEPRECATED)
1560
1561=over 4
1562
1563=item Arguments: $target_namespace, @db_info
1564
1565=item Return Value: $new_schema
1566
1567=back
1568
1569DEPRECATED. You probably wanted compose_namespace.
1570
1571Actually, you probably just wanted to call connect.
1572
1573=begin hidden
1574
1575(hidden due to deprecation)
1576
1577Calls L<DBIx::Class::Schema/"compose_namespace"> to the target namespace,
1578calls L<DBIx::Class::Schema/connection> with @db_info on the new schema,
1579then injects the L<DBix::Class::ResultSetProxy> component and a
1580resultset_instance classdata entry on all the new classes, in order to support
1581$target_namespaces::$class->search(...) method calls.
1582
1583This is primarily useful when you have a specific need for class method access
1584to a connection. In normal usage it is preferred to call
1585L<DBIx::Class::Schema/connect> and use the resulting schema object to operate
1586on L<DBIx::Class::ResultSet> objects with L<DBIx::Class::Schema/resultset> for
1587more information.
1588
1589=end hidden
1590
1591=cut
1592
e42bbd7f 1593sub compose_connection {
1594 my ($self, $target, @info) = @_;
829517d4 1595
e42bbd7f 1596 carp_once "compose_connection deprecated as of 0.08000"
1597 unless $INC{"DBIx/Class/CDBICompat.pm"};
d4daee7b 1598
ddcc02d1 1599 dbic_internal_try {
63a18cfe 1600 require DBIx::Class::ResultSetProxy;
e42bbd7f 1601 }
1602 catch {
1603 $self->throw_exception
63a18cfe 1604 ("No arguments to load_classes and couldn't load DBIx::Class::ResultSetProxy ($_)")
e42bbd7f 1605 };
d4daee7b 1606
e42bbd7f 1607 if ($self eq $target) {
1608 # Pathological case, largely caused by the docs on early C::M::DBIC::Plain
fb13a49f 1609 foreach my $source_name ($self->sources) {
1610 my $source = $self->source($source_name);
829517d4 1611 my $class = $source->result_class;
63a18cfe 1612 $self->inject_base($class, 'DBIx::Class::ResultSetProxy');
e5053694 1613 $class->mk_classaccessor(resultset_instance => $source->resultset);
1614 $class->mk_classaccessor(class_resolver => $self);
829517d4 1615 }
e42bbd7f 1616 $self->connection(@info);
1617 return $self;
1618 }
1619
63a18cfe 1620 my $schema = $self->compose_namespace($target, 'DBIx::Class::ResultSetProxy');
8d73fcd4 1621 quote_sub "${target}::schema", '$s', { '$s' => \$schema };
e42bbd7f 1622
1623 $schema->connection(@info);
fb13a49f 1624 foreach my $source_name ($schema->sources) {
1625 my $source = $schema->source($source_name);
e42bbd7f 1626 my $class = $source->result_class;
fb13a49f 1627 #warn "$source_name $class $source ".$source->storage;
f064a2ab 1628
1629 $class->mk_group_accessors( inherited => [ result_source_instance => '_result_source' ] );
1630 # explicit set-call, avoid mro update lag
1631 $class->set_inherited( result_source_instance => $source );
1632
e5053694 1633 $class->mk_classaccessor(resultset_instance => $source->resultset);
1634 $class->mk_classaccessor(class_resolver => $schema);
e42bbd7f 1635 }
1636 return $schema;
829517d4 1637}
1638
a2bd3796 1639=head1 FURTHER QUESTIONS?
c2da098a 1640
a2bd3796 1641Check the list of L<additional DBIC resources|DBIx::Class/GETTING HELP/SUPPORT>.
c2da098a 1642
a2bd3796 1643=head1 COPYRIGHT AND LICENSE
c2da098a 1644
a2bd3796 1645This module is free software L<copyright|DBIx::Class/COPYRIGHT AND LICENSE>
1646by the L<DBIx::Class (DBIC) authors|DBIx::Class/AUTHORS>. You can
1647redistribute it and/or modify it under the same terms as the
1648L<DBIx::Class library|DBIx::Class/COPYRIGHT AND LICENSE>.
c2da098a 1649
1650=cut
a2bd3796 1651
16521;