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