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