added register_extra_source
[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);
2a4d9487 916 $clone->_unregister_source($moniker);
66d9ef6b 917 $clone->register_source($moniker => $new);
918 }
82cc0386 919 $clone->storage->set_schema($clone) if $clone->storage;
66d9ef6b 920 return $clone;
921}
922
87c4e602 923=head2 populate
924
27f01d1f 925=over 4
926
16c5f7d3 927=item Arguments: $source_name, \@data;
27f01d1f 928
929=back
a37a4697 930
16c5f7d3 931Pass this method a resultsource name, and an arrayref of
932arrayrefs. The arrayrefs should contain a list of column names,
933followed by one or many sets of matching data for the given columns.
934
744076d8 935In void context, C<insert_bulk> in L<DBIx::Class::Storage::DBI> is used
936to insert the data, as this is a fast method. However, insert_bulk currently
937assumes that your datasets all contain the same type of values, using scalar
938references in a column in one row, and not in another will probably not work.
939
940Otherwise, each set of data is inserted into the database using
16c5f7d3 941L<DBIx::Class::ResultSet/create>, and a arrayref of the resulting row
942objects is returned.
82b01c38 943
944i.e.,
a37a4697 945
24d67825 946 $schema->populate('Artist', [
947 [ qw/artistid name/ ],
948 [ 1, 'Popular Band' ],
949 [ 2, 'Indie Band' ],
a62cf8d4 950 ...
951 ]);
5a93e138 952
953Since wantarray context is basically the same as looping over $rs->create(...)
954you won't see any performance benefits and in this case the method is more for
955convenience. Void context sends the column information directly to storage
956using <DBI>s bulk insert method. So the performance will be much better for
957storages that support this method.
958
959Because of this difference in the way void context inserts rows into your
960database you need to note how this will effect any loaded components that
961override or augment insert. For example if you are using a component such
962as L<DBIx::Class::UUIDColumns> to populate your primary keys you MUST use
963wantarray context if you want the PKs automatically created.
a37a4697 964
965=cut
966
967sub populate {
968 my ($self, $name, $data) = @_;
969 my $rs = $self->resultset($name);
970 my @names = @{shift(@$data)};
54e0bd06 971 if(defined wantarray) {
972 my @created;
973 foreach my $item (@$data) {
974 my %create;
975 @create{@names} = @$item;
976 push(@created, $rs->create(\%create));
977 }
978 return @created;
a37a4697 979 }
8b93a938 980 my @results_to_create;
981 foreach my $datum (@$data) {
982 my %result_to_create;
983 foreach my $index (0..$#names) {
984 $result_to_create{$names[$index]} = $$datum[$index];
985 }
986 push @results_to_create, \%result_to_create;
987 }
988 $rs->populate(\@results_to_create);
a37a4697 989}
990
82cc0386 991=head2 exception_action
992
993=over 4
994
995=item Arguments: $code_reference
996
997=back
998
db5dc233 999If C<exception_action> is set for this class/object, L</throw_exception>
1000will prefer to call this code reference with the exception as an argument,
613397e7 1001rather than its normal C<croak> or C<confess> action.
db5dc233 1002
1003Your subroutine should probably just wrap the error in the exception
1004object/class of your choosing and rethrow. If, against all sage advice,
1005you'd like your C<exception_action> to suppress a particular exception
1006completely, simply have it return true.
82cc0386 1007
1008Example:
1009
1010 package My::Schema;
1011 use base qw/DBIx::Class::Schema/;
1012 use My::ExceptionClass;
1013 __PACKAGE__->exception_action(sub { My::ExceptionClass->throw(@_) });
1014 __PACKAGE__->load_classes;
1015
db5dc233 1016 # or:
82cc0386 1017 my $schema_obj = My::Schema->connect( .... );
1018 $schema_obj->exception_action(sub { My::ExceptionClass->throw(@_) });
1019
db5dc233 1020 # suppress all exceptions, like a moron:
1021 $schema_obj->exception_action(sub { 1 });
1022
613397e7 1023=head2 stacktrace
1024
84c5863b 1025=over 4
613397e7 1026
1027=item Arguments: boolean
1028
1029=back
1030
4981dc70 1031Whether L</throw_exception> should include stack trace information.
4b946902 1032Defaults to false normally, but defaults to true if C<$ENV{DBIC_TRACE}>
1033is true.
613397e7 1034
5160b401 1035=head2 throw_exception
701da8c4 1036
75d07914 1037=over 4
82b01c38 1038
ebc77b53 1039=item Arguments: $message
82b01c38 1040
1041=back
1042
1043Throws an exception. Defaults to using L<Carp::Clan> to report errors from
db5dc233 1044user's perspective. See L</exception_action> for details on overriding
4b946902 1045this method's behavior. If L</stacktrace> is turned on, C<throw_exception>'s
1046default behavior will provide a detailed stack trace.
701da8c4 1047
1048=cut
1049
1050sub throw_exception {
82cc0386 1051 my $self = shift;
4981dc70 1052
1053 DBIx::Class::Exception->throw($_[0], $self->stacktrace)
1054 if !$self->exception_action || !$self->exception_action->(@_);
701da8c4 1055}
1056
dfccde48 1057=head2 deploy
1c339d71 1058
82b01c38 1059=over 4
1060
6e73ac25 1061=item Arguments: $sqlt_args, $dir
82b01c38 1062
1063=back
1064
1065Attempts to deploy the schema to the current storage using L<SQL::Translator>.
ec6704d4 1066
51bace1c 1067See L<SQL::Translator/METHODS> for a list of values for C<$sqlt_args>. The most
1068common value for this would be C<< { add_drop_table => 1, } >> to have the SQL
1069produced include a DROP TABLE statement for each table created.
1070
499adf63 1071Additionally, the DBIx::Class parser accepts a C<sources> parameter as a hash
1072ref or an array ref, containing a list of source to deploy. If present, then
0e2c6809 1073only the sources listed will get deployed. Furthermore, you can use the
1074C<add_fk_index> parser parameter to prevent the parser from creating an index for each
1075FK.
499adf63 1076
1c339d71 1077=cut
1078
1079sub deploy {
6e73ac25 1080 my ($self, $sqltargs, $dir) = @_;
1c339d71 1081 $self->throw_exception("Can't deploy without storage") unless $self->storage;
6e73ac25 1082 $self->storage->deploy($self, undef, $sqltargs, $dir);
1c339d71 1083}
1084
0e0ce6c1 1085=head2 deployment_statements
1086
1087=over 4
1088
1089=item Arguments: $rdbms_type
1090
1091=back
1092
1093Returns the SQL statements used by L</deploy> and L<DBIx::Class::Schema/deploy>.
1094C<$rdbms_type> provides the DBI database driver name for which the SQL
1095statements are produced. If not supplied, the type of the current schema storage
1096will be used.
1097
1098=cut
1099
1100sub deployment_statements {
1101 my ($self, $rdbms_type) = @_;
1102
1103 $self->throw_exception("Can't generate deployment statements without a storage")
1104 if not $self->storage;
1105
1106 $self->storage->deployment_statements($self, $rdbms_type);
1107}
1108
c0f61310 1109=head2 create_ddl_dir (EXPERIMENTAL)
1110
1111=over 4
1112
c9d2e0a2 1113=item Arguments: \@databases, $version, $directory, $preversion, $sqlt_args
c0f61310 1114
1115=back
1116
1117Creates an SQL file based on the Schema, for each of the specified
c9d2e0a2 1118database types, in the given directory. Given a previous version number,
1119this will also create a file containing the ALTER TABLE statements to
1120transform the previous schema into the current one. Note that these
1121statements may contain DROP TABLE or DROP COLUMN statements that can
1122potentially destroy data.
1123
1124The file names are created using the C<ddl_filename> method below, please
1125override this method in your schema if you would like a different file
1126name format. For the ALTER file, the same format is used, replacing
1127$version in the name with "$preversion-$version".
1128
0e2c6809 1129See L<DBIx::Class::Schema/deploy> for details of $sqlt_args.
1130
c9d2e0a2 1131If no arguments are passed, then the following default values are used:
1132
1133=over 4
1134
1135=item databases - ['MySQL', 'SQLite', 'PostgreSQL']
1136
1137=item version - $schema->VERSION
1138
1139=item directory - './'
1140
1141=item preversion - <none>
1142
1143=back
c0f61310 1144
1145Note that this feature is currently EXPERIMENTAL and may not work correctly
1146across all databases, or fully handle complex relationships.
1147
c9d2e0a2 1148WARNING: Please check all SQL files created, before applying them.
1149
c0f61310 1150=cut
1151
6e73ac25 1152sub create_ddl_dir {
e673f011 1153 my $self = shift;
1154
1155 $self->throw_exception("Can't create_ddl_dir without storage") unless $self->storage;
1156 $self->storage->create_ddl_dir($self, @_);
1157}
1158
e63a82f7 1159=head2 ddl_filename
9b83fccd 1160
c9d2e0a2 1161=over 4
1162
99a74c4a 1163=item Arguments: $database-type, $version, $directory, $preversion
c9d2e0a2 1164
1165=back
1166
99a74c4a 1167 my $filename = $table->ddl_filename($type, $version, $dir, $preversion)
c9d2e0a2 1168
1169This method is called by C<create_ddl_dir> to compose a file name out of
1170the supplied directory, database type and version number. The default file
1171name format is: C<$dir$schema-$version-$type.sql>.
9b83fccd 1172
c9d2e0a2 1173You may override this method in your schema if you wish to use a different
1174format.
9b83fccd 1175
1176=cut
1177
6e73ac25 1178sub ddl_filename {
99a74c4a 1179 my ($self, $type, $version, $dir, $preversion) = @_;
e673f011 1180
99a74c4a 1181 my $filename = ref($self);
1182 $filename =~ s/::/-/g;
1183 $filename = File::Spec->catfile($dir, "$filename-$version-$type.sql");
1184 $filename =~ s/$version/$preversion-$version/ if($preversion);
1185
1186 return $filename;
e673f011 1187}
1188
d2f3e87b 1189=head2 sqlt_deploy_hook($sqlt_schema)
1190
1191An optional sub which you can declare in your own Schema class that will get
1192passed the L<SQL::Translator::Schema> object when you deploy the schema via
1193L</create_ddl_dir> or L</deploy>.
1194
1195For an example of what you can do with this, see
1196L<DBIx::Class::Manual::Cookbook/Adding Indexes And Functions To Your SQL>.
1197
4146e3da 1198=head2 thaw
1199
1200Provided as the recommened way of thawing schema objects. You can call
1201C<Storable::thaw> directly if you wish, but the thawed objects will not have a
1202reference to any schema, so are rather useless
1203
1204=cut
1205
1206sub thaw {
1207 my ($self, $obj) = @_;
1208 local $DBIx::Class::ResultSourceHandle::thaw_schema = $self;
1209 return Storable::thaw($obj);
1210}
1211
1212=head2 freeze
1213
1214This doesn't actualy do anything more than call L<Storable/freeze>, it is just
1215provided here for symetry.
1216
d2f3e87b 1217=cut
1218
4146e3da 1219sub freeze {
1220 return Storable::freeze($_[1]);
1221}
1222
1223=head2 dclone
1224
1225Recommeneded way of dcloning objects. This is needed to properly maintain
1226references to the schema object (which itself is B<not> cloned.)
1227
1228=cut
1229
1230sub dclone {
1231 my ($self, $obj) = @_;
1232 local $DBIx::Class::ResultSourceHandle::thaw_schema = $self;
1233 return Storable::dclone($obj);
1234}
1235
93e4d41a 1236=head2 schema_version
1237
1238Returns the current schema class' $VERSION
1239
1240=cut
1241
1242sub schema_version {
1243 my ($self) = @_;
1244 my $class = ref($self)||$self;
1245
1246 # does -not- use $schema->VERSION
1247 # since that varies in results depending on if version.pm is installed, and if
1248 # so the perl or XS versions. If you want this to change, bug the version.pm
1249 # author to make vpp and vxs behave the same.
1250
1251 my $version;
1252 {
1253 no strict 'refs';
1254 $version = ${"${class}::VERSION"};
1255 }
1256 return $version;
1257}
1258
a02675cd 12591;
c2da098a 1260
c2da098a 1261=head1 AUTHORS
1262
daec44b8 1263Matt S. Trout <mst@shadowcatsystems.co.uk>
c2da098a 1264
1265=head1 LICENSE
1266
1267You may distribute this code under the same terms as Perl itself.
1268
1269=cut