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