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