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