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