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