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