Merge 'trunk' into 'DBIx-Class-current'
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / Schema.pm
CommitLineData
a02675cd 1package DBIx::Class::Schema;
2
3use strict;
4use warnings;
aa562407 5
701da8c4 6use Carp::Clan qw/^DBIx::Class/;
a917fb06 7use Scalar::Util qw/weaken/;
7cb86b38 8require Module::Find;
a02675cd 9
41a6f8c0 10use base qw/DBIx::Class/;
a02675cd 11
0dc79249 12__PACKAGE__->mk_classdata('class_mappings' => {});
13__PACKAGE__->mk_classdata('source_registrations' => {});
1e10a11d 14__PACKAGE__->mk_classdata('storage_type' => '::DBI');
d7156e50 15__PACKAGE__->mk_classdata('storage');
82cc0386 16__PACKAGE__->mk_classdata('exception_action');
a02675cd 17
c2da098a 18=head1 NAME
19
20DBIx::Class::Schema - composable schemas
21
22=head1 SYNOPSIS
23
24d67825 24 package Library::Schema;
c2da098a 25 use base qw/DBIx::Class::Schema/;
bab77431 26
24d67825 27 # load Library::Schema::CD, Library::Schema::Book, Library::Schema::DVD
28 __PACKAGE__->load_classes(qw/CD Book DVD/);
c2da098a 29
24d67825 30 package Library::Schema::CD;
03312470 31 use base qw/DBIx::Class/;
77254782 32 __PACKAGE__->load_components(qw/PK::Auto Core/); # for example
24d67825 33 __PACKAGE__->table('cd');
c2da098a 34
5d9076f2 35 # Elsewhere in your code:
24d67825 36 my $schema1 = Library::Schema->connect(
a3d93194 37 $dsn,
38 $user,
39 $password,
24d67825 40 { AutoCommit => 0 },
a3d93194 41 );
bab77431 42
24d67825 43 my $schema2 = Library::Schema->connect($coderef_returning_dbh);
c2da098a 44
24d67825 45 # fetch objects using Library::Schema::DVD
46 my $resultset = $schema1->resultset('DVD')->search( ... );
47 my @dvd_objects = $schema2->resultset('DVD')->search( ... );
c2da098a 48
49=head1 DESCRIPTION
50
a3d93194 51Creates database classes based on a schema. This is the recommended way to
52use L<DBIx::Class> and allows you to use more than one concurrent connection
53with your classes.
429bd4f1 54
03312470 55NB: If you're used to L<Class::DBI> it's worth reading the L</SYNOPSIS>
2053ab2a 56carefully, as DBIx::Class does things a little differently. Note in
03312470 57particular which module inherits off which.
58
c2da098a 59=head1 METHODS
60
87c4e602 61=head2 register_class
62
27f01d1f 63=over 4
64
ebc77b53 65=item Arguments: $moniker, $component_class
27f01d1f 66
67=back
076652e8 68
71f9df37 69Registers a class which isa DBIx::Class::ResultSourceProxy. Equivalent to
2053ab2a 70calling:
66d9ef6b 71
181a28f4 72 $schema->register_source($moniker, $component_class->result_source_instance);
076652e8 73
c2da098a 74=cut
75
a02675cd 76sub register_class {
0dc79249 77 my ($self, $moniker, $to_register) = @_;
78 $self->register_source($moniker => $to_register->result_source_instance);
74b92d9a 79}
80
87c4e602 81=head2 register_source
82
27f01d1f 83=over 4
84
ebc77b53 85=item Arguments: $moniker, $result_source
27f01d1f 86
87=back
076652e8 88
82b01c38 89Registers the L<DBIx::Class::ResultSource> in the schema with the given
90moniker.
076652e8 91
92=cut
93
0dc79249 94sub register_source {
95 my ($self, $moniker, $source) = @_;
96 my %reg = %{$self->source_registrations};
97 $reg{$moniker} = $source;
98 $self->source_registrations(\%reg);
99 $source->schema($self);
a917fb06 100 weaken($source->{schema}) if ref($self);
0dc79249 101 if ($source->result_class) {
102 my %map = %{$self->class_mappings};
103 $map{$source->result_class} = $moniker;
104 $self->class_mappings(\%map);
105 }
75d07914 106}
a02675cd 107
bfb2bd4f 108=head2 class
109
27f01d1f 110=over 4
82b01c38 111
ebc77b53 112=item Arguments: $moniker
27f01d1f 113
d601dc88 114=item Return Value: $classname
27f01d1f 115
116=back
82b01c38 117
2053ab2a 118Retrieves the result class name for the given moniker. For example:
82b01c38 119
120 my $class = $schema->class('CD');
bfb2bd4f 121
122=cut
123
124sub class {
0dc79249 125 my ($self, $moniker) = @_;
126 return $self->source($moniker)->result_class;
bfb2bd4f 127}
128
ea20d0fd 129=head2 source
130
27f01d1f 131=over 4
132
ebc77b53 133=item Arguments: $moniker
27f01d1f 134
d601dc88 135=item Return Value: $result_source
82b01c38 136
27f01d1f 137=back
82b01c38 138
24d67825 139 my $source = $schema->source('Book');
ea20d0fd 140
82b01c38 141Returns the L<DBIx::Class::ResultSource> object for the registered moniker.
ea20d0fd 142
143=cut
144
145sub source {
0dc79249 146 my ($self, $moniker) = @_;
147 my $sreg = $self->source_registrations;
148 return $sreg->{$moniker} if exists $sreg->{$moniker};
149
150 # if we got here, they probably passed a full class name
151 my $mapped = $self->class_mappings->{$moniker};
701da8c4 152 $self->throw_exception("Can't find source for ${moniker}")
0dc79249 153 unless $mapped && exists $sreg->{$mapped};
154 return $sreg->{$mapped};
ea20d0fd 155}
156
0dc79249 157=head2 sources
158
27f01d1f 159=over 4
160
d601dc88 161=item Return Value: @source_monikers
27f01d1f 162
163=back
82b01c38 164
165Returns the source monikers of all source registrations on this schema.
2053ab2a 166For example:
82b01c38 167
168 my @source_monikers = $schema->sources;
0dc79249 169
170=cut
171
172sub sources { return keys %{shift->source_registrations}; }
173
9b1ba0f2 174=head2 storage
175
176 my $storage = $schema->storage;
177
178Returns the L<DBIx::Class::Storage> object for this Schema.
179
ea20d0fd 180=head2 resultset
181
27f01d1f 182=over 4
183
ebc77b53 184=item Arguments: $moniker
27f01d1f 185
d601dc88 186=item Return Value: $result_set
82b01c38 187
27f01d1f 188=back
82b01c38 189
24d67825 190 my $rs = $schema->resultset('DVD');
ea20d0fd 191
82b01c38 192Returns the L<DBIx::Class::ResultSet> object for the registered moniker.
ea20d0fd 193
194=cut
195
196sub resultset {
0dc79249 197 my ($self, $moniker) = @_;
198 return $self->source($moniker)->resultset;
ea20d0fd 199}
200
87c4e602 201=head2 load_classes
202
27f01d1f 203=over 4
204
205=item Arguments: @classes?, { $namespace => [ @classes ] }+
206
207=back
076652e8 208
82b01c38 209With no arguments, this method uses L<Module::Find> to find all classes under
210the schema's namespace. Otherwise, this method loads the classes you specify
211(using L<use>), and registers them (using L</"register_class">).
076652e8 212
2053ab2a 213It is possible to comment out classes with a leading C<#>, but note that perl
214will think it's a mistake (trying to use a comment in a qw list), so you'll
215need to add C<no warnings 'qw';> before your load_classes call.
5ce32fc1 216
2053ab2a 217Example:
82b01c38 218
219 My::Schema->load_classes(); # loads My::Schema::CD, My::Schema::Artist,
75d07914 220 # etc. (anything under the My::Schema namespace)
82b01c38 221
222 # loads My::Schema::CD, My::Schema::Artist, Other::Namespace::Producer but
223 # not Other::Namespace::LinerNotes nor My::Schema::Track
224 My::Schema->load_classes(qw/ CD Artist #Track /, {
225 Other::Namespace => [qw/ Producer #LinerNotes /],
226 });
227
076652e8 228=cut
229
a02675cd 230sub load_classes {
5ce32fc1 231 my ($class, @params) = @_;
bab77431 232
5ce32fc1 233 my %comps_for;
bab77431 234
5ce32fc1 235 if (@params) {
236 foreach my $param (@params) {
237 if (ref $param eq 'ARRAY') {
238 # filter out commented entries
239 my @modules = grep { $_ !~ /^#/ } @$param;
bab77431 240
5ce32fc1 241 push (@{$comps_for{$class}}, @modules);
242 }
243 elsif (ref $param eq 'HASH') {
244 # more than one namespace possible
245 for my $comp ( keys %$param ) {
246 # filter out commented entries
247 my @modules = grep { $_ !~ /^#/ } @{$param->{$comp}};
248
249 push (@{$comps_for{$comp}}, @modules);
250 }
251 }
252 else {
253 # filter out commented entries
254 push (@{$comps_for{$class}}, $param) if $param !~ /^#/;
255 }
256 }
257 } else {
bc0c9800 258 my @comp = map { substr $_, length "${class}::" }
259 Module::Find::findallmod($class);
5ce32fc1 260 $comps_for{$class} = \@comp;
41a6f8c0 261 }
5ce32fc1 262
e6efde04 263 my @to_register;
264 {
265 no warnings qw/redefine/;
266 local *Class::C3::reinitialize = sub { };
267 foreach my $prefix (keys %comps_for) {
268 foreach my $comp (@{$comps_for{$prefix}||[]}) {
269 my $comp_class = "${prefix}::${comp}";
c037c03a 270 $class->ensure_class_loaded($comp_class);
bab77431 271 $comp_class->source_name($comp) unless $comp_class->source_name;
272
273 push(@to_register, [ $comp_class->source_name, $comp_class ]);
bfb2bd4f 274 }
5ce32fc1 275 }
a02675cd 276 }
e6efde04 277 Class::C3->reinitialize;
278
279 foreach my $to (@to_register) {
280 $class->register_class(@$to);
281 # if $class->can('result_source_instance');
282 }
a02675cd 283}
284
2374c5ff 285=head2 load_namespaces
286
287=over 4
288
85bd0538 289=item Arguments: %options?
2374c5ff 290
291=back
292
293This is an alternative to L</load_classes> above which assumes an alternative
c87014e8 294layout for automatic class loading. It assumes that all result
295classes are underneath a sub-namespace of the schema called C<Result>, any
7a58f051 296corresponding ResultSet classes are underneath a sub-namespace of the schema
46a05fd4 297called C<ResultSet>.
2374c5ff 298
46a05fd4 299Both of the sub-namespaces are configurable if you don't like the defaults,
c87014e8 300via the options C<result_namespace> and C<resultset_namespace>.
85bd0538 301
25fb14bd 302If (and only if) you specify the option C<default_resultset_class>, any found
c87014e8 303Result classes for which we do not find a corresponding
25fb14bd 304ResultSet class will have their C<resultset_class> set to
305C<default_resultset_class>.
0f4ec1d2 306
46a05fd4 307C<load_namespaces> takes care of calling C<resultset_class> for you where
308neccessary if you didn't do it for yourself.
f017c022 309
0f4ec1d2 310All of the namespace and classname options to this method are relative to
311the schema classname by default. To specify a fully-qualified name, prefix
312it with a literal C<+>.
2374c5ff 313
f017c022 314Examples:
2374c5ff 315
c87014e8 316 # load My::Schema::Result::CD, My::Schema::Result::Artist,
2374c5ff 317 # My::Schema::ResultSet::CD, etc...
0f4ec1d2 318 My::Schema->load_namespaces;
319
c87014e8 320 # Override everything to use ugly names.
321 # In this example, if there is a My::Schema::Res::Foo, but no matching
322 # My::Schema::RSets::Foo, then Foo will have its
323 # resultset_class set to My::Schema::RSetBase
0f4ec1d2 324 My::Schema->load_namespaces(
c87014e8 325 result_namespace => 'Res',
0f4ec1d2 326 resultset_namespace => 'RSets',
25fb14bd 327 default_resultset_class => 'RSetBase',
0f4ec1d2 328 );
2374c5ff 329
0f4ec1d2 330 # Put things in other namespaces
85bd0538 331 My::Schema->load_namespaces(
c87014e8 332 result_namespace => '+Some::Place::Results',
0f4ec1d2 333 resultset_namespace => '+Another::Place::RSets',
85bd0538 334 );
0f4ec1d2 335
f017c022 336If you'd like to use multiple namespaces of each type, simply use an arrayref
c87014e8 337of namespaces for that option. In the case that the same result
46a05fd4 338(or resultset) class exists in multiple namespaces, the latter entries in
339your list of namespaces will override earlier ones.
f017c022 340
341 My::Schema->load_namespaces(
c87014e8 342 # My::Schema::Results_C::Foo takes precedence over My::Schema::Results_B::Foo :
343 result_namespace => [ 'Results_A', 'Results_B', 'Results_C' ],
f017c022 344 resultset_namespace => [ '+Some::Place::RSets', 'RSets' ],
345 );
85bd0538 346
2374c5ff 347=cut
348
f017c022 349# Pre-pends our classname to the given relative classname or
350# class namespace, unless there is a '+' prefix, which will
7a58f051 351# be stripped.
f017c022 352sub _expand_relative_name {
7a58f051 353 my ($class, $name) = @_;
354 return if !$name;
355 $name = $class . '::' . $name if ! ($name =~ s/^\+//);
356 return $name;
f017c022 357}
358
359# returns a hash of $shortname => $fullname for every package
360# found in the given namespaces ($shortname is with the $fullname's
361# namespace stripped off)
362sub _map_namespaces {
363 my ($class, @namespaces) = @_;
364
365 my @results_hash;
366 foreach my $namespace (@namespaces) {
367 push(
368 @results_hash,
369 map { (substr($_, length "${namespace}::"), $_) }
370 Module::Find::findallmod($namespace)
371 );
372 }
373
374 @results_hash;
375}
376
2374c5ff 377sub load_namespaces {
85bd0538 378 my ($class, %args) = @_;
2374c5ff 379
c87014e8 380 my $result_namespace = delete $args{result_namespace} || 'Result';
25fb14bd 381 my $resultset_namespace = delete $args{resultset_namespace} || 'ResultSet';
25fb14bd 382 my $default_resultset_class = delete $args{default_resultset_class};
0f4ec1d2 383
25fb14bd 384 $class->throw_exception('load_namespaces: unknown option(s): '
385 . join(q{,}, map { qq{'$_'} } keys %args))
386 if scalar keys %args;
387
7a58f051 388 $default_resultset_class
389 = $class->_expand_relative_name($default_resultset_class);
f017c022 390
c87014e8 391 for my $arg ($result_namespace, $resultset_namespace) {
f017c022 392 $arg = [ $arg ] if !ref($arg) && $arg;
2374c5ff 393
f017c022 394 $class->throw_exception('load_namespaces: namespace arguments must be '
395 . 'a simple string or an arrayref')
396 if ref($arg) ne 'ARRAY';
2374c5ff 397
7a58f051 398 $_ = $class->_expand_relative_name($_) for (@$arg);
f017c022 399 }
2374c5ff 400
c87014e8 401 my %results = $class->_map_namespaces(@$result_namespace);
f017c022 402 my %resultsets = $class->_map_namespaces(@$resultset_namespace);
0f4ec1d2 403
2374c5ff 404 my @to_register;
405 {
25fb14bd 406 no warnings 'redefine';
2374c5ff 407 local *Class::C3::reinitialize = sub { };
25fb14bd 408 use warnings 'redefine';
0f4ec1d2 409
c87014e8 410 foreach my $result (keys %results) {
411 my $result_class = $results{$result};
412 $class->ensure_class_loaded($result_class);
413 $result_class->source_name($result) unless $result_class->source_name;
0f4ec1d2 414
c87014e8 415 my $rs_class = delete $resultsets{$result};
416 my $rs_set = $result_class->resultset_class;
25fb14bd 417 if($rs_set && $rs_set ne 'DBIx::Class::ResultSet') {
f017c022 418 if($rs_class && $rs_class ne $rs_set) {
c87014e8 419 warn "We found ResultSet class '$rs_class' for '$result', but it seems "
420 . "that you had already set '$result' to use '$rs_set' instead";
2374c5ff 421 }
422 }
25fb14bd 423 elsif($rs_class ||= $default_resultset_class) {
424 $class->ensure_class_loaded($rs_class);
c87014e8 425 $result_class->resultset_class($rs_class);
0f4ec1d2 426 }
2374c5ff 427
c87014e8 428 push(@to_register, [ $result_class->source_name, $result_class ]);
2374c5ff 429 }
430 }
431
0f4ec1d2 432 foreach (sort keys %resultsets) {
433 warn "load_namespaces found ResultSet class $_ with no "
c87014e8 434 . 'corresponding Result class';
2374c5ff 435 }
0f4ec1d2 436
fdcd8145 437 Class::C3->reinitialize;
438 $class->register_class(@$_) for (@to_register);
439
0f4ec1d2 440 return;
2374c5ff 441}
442
87c4e602 443=head2 compose_connection
444
27f01d1f 445=over 4
446
ebc77b53 447=item Arguments: $target_namespace, @db_info
429bd4f1 448
d601dc88 449=item Return Value: $new_schema
27f01d1f 450
451=back
076652e8 452
2053ab2a 453Calls L<DBIx::Class::Schema/"compose_namespace"> to the target namespace,
454calls L<DBIx::Class::Schema/connection> with @db_info on the new schema,
455then injects the L<DBix::Class::ResultSetProxy> component and a
456resultset_instance classdata entry on all the new classes, in order to support
82b01c38 457$target_namespaces::$class->search(...) method calls.
458
459This is primarily useful when you have a specific need for class method access
460to a connection. In normal usage it is preferred to call
461L<DBIx::Class::Schema/connect> and use the resulting schema object to operate
462on L<DBIx::Class::ResultSet> objects with L<DBIx::Class::Schema/resultset> for
463more information.
54540863 464
076652e8 465=cut
466
a02675cd 467sub compose_connection {
ea20d0fd 468 my ($self, $target, @info) = @_;
80c90f5d 469 my $base = 'DBIx::Class::ResultSetProxy';
8ef144ff 470 eval "require ${base};";
bc0c9800 471 $self->throw_exception
472 ("No arguments to load_classes and couldn't load ${base} ($@)")
473 if $@;
be381829 474
475 if ($self eq $target) {
476 # Pathological case, largely caused by the docs on early C::M::DBIC::Plain
477 foreach my $moniker ($self->sources) {
478 my $source = $self->source($moniker);
479 my $class = $source->result_class;
480 $self->inject_base($class, $base);
481 $class->mk_classdata(resultset_instance => $source->resultset);
482 $class->mk_classdata(class_resolver => $self);
483 }
50041f3c 484 $self->connection(@info);
be381829 485 return $self;
486 }
487
66d9ef6b 488 my $schema = $self->compose_namespace($target, $base);
ecceadff 489 {
490 no strict 'refs';
491 *{"${target}::schema"} = sub { $schema };
492 }
493
66d9ef6b 494 $schema->connection(@info);
0dc79249 495 foreach my $moniker ($schema->sources) {
496 my $source = $schema->source($moniker);
497 my $class = $source->result_class;
498 #warn "$moniker $class $source ".$source->storage;
8c49f629 499 $class->mk_classdata(result_source_instance => $source);
ea20d0fd 500 $class->mk_classdata(resultset_instance => $source->resultset);
66d9ef6b 501 $class->mk_classdata(class_resolver => $schema);
bfb2bd4f 502 }
503 return $schema;
e678398e 504}
505
77254782 506=head2 compose_namespace
507
27f01d1f 508=over 4
509
510=item Arguments: $target_namespace, $additional_base_class?
82b01c38 511
d601dc88 512=item Return Value: $new_schema
27f01d1f 513
514=back
13765dad 515
82b01c38 516For each L<DBIx::Class::ResultSource> in the schema, this method creates a
517class in the target namespace (e.g. $target_namespace::CD,
518$target_namespace::Artist) that inherits from the corresponding classes
519attached to the current schema.
77254782 520
82b01c38 521It also attaches a corresponding L<DBIx::Class::ResultSource> object to the
522new $schema object. If C<$additional_base_class> is given, the new composed
523classes will inherit from first the corresponding classe from the current
524schema then the base class.
525
2053ab2a 526For example, for a schema with My::Schema::CD and My::Schema::Artist classes,
82b01c38 527
528 $schema->compose_namespace('My::DB', 'Base::Class');
529 print join (', ', @My::DB::CD::ISA) . "\n";
530 print join (', ', @My::DB::Artist::ISA) ."\n";
531
2053ab2a 532will produce the output
82b01c38 533
534 My::Schema::CD, Base::Class
535 My::Schema::Artist, Base::Class
77254782 536
537=cut
538
e678398e 539sub compose_namespace {
66d9ef6b 540 my ($self, $target, $base) = @_;
541 my %reg = %{ $self->source_registrations };
11b78bd6 542 my %target;
543 my %map;
66d9ef6b 544 my $schema = $self->clone;
e9100ff7 545 {
546 no warnings qw/redefine/;
547 local *Class::C3::reinitialize = sub { };
548 foreach my $moniker ($schema->sources) {
549 my $source = $schema->source($moniker);
550 my $target_class = "${target}::${moniker}";
551 $self->inject_base(
552 $target_class => $source->result_class, ($base ? $base : ())
553 );
554 $source->result_class($target_class);
9d3d5af3 555 $target_class->result_source_instance($source)
556 if $target_class->can('result_source_instance');
e9100ff7 557 }
b7951443 558 }
e9100ff7 559 Class::C3->reinitialize();
11b78bd6 560 {
561 no strict 'refs';
1edaf6fe 562 foreach my $meth (qw/class source resultset/) {
563 *{"${target}::${meth}"} =
564 sub { shift->schema->$meth(@_) };
565 }
11b78bd6 566 }
bfb2bd4f 567 return $schema;
b7951443 568}
569
87c4e602 570=head2 setup_connection_class
571
27f01d1f 572=over 4
573
ebc77b53 574=item Arguments: $target, @info
27f01d1f 575
576=back
076652e8 577
82b01c38 578Sets up a database connection class to inject between the schema and the
579subclasses that the schema creates.
429bd4f1 580
076652e8 581=cut
582
b7951443 583sub setup_connection_class {
584 my ($class, $target, @info) = @_;
63e9583a 585 $class->inject_base($target => 'DBIx::Class::DB');
586 #$target->load_components('DB');
b7951443 587 $target->connection(@info);
588}
589
6b43ba5f 590=head2 storage_type
591
592=over 4
593
594=item Arguments: $storage_type
595
596=item Return Value: $storage_type
597
598=back
599
600Set the storage class that will be instantiated when L</connect> is called.
601If the classname starts with C<::>, the prefix C<DBIx::Class::Storage> is
602assumed by L</connect>. Defaults to C<::DBI>,
603which is L<DBIx::Class::Storage::DBI>.
604
605You want to use this to hardcoded subclasses of L<DBIx::Class::Storage::DBI>
606in cases where the appropriate subclass is not autodetected, such as when
607dealing with MSSQL via L<DBD::Sybase>, in which case you'd set it to
608C<::DBI::Sybase::MSSQL>.
609
87c4e602 610=head2 connection
611
27f01d1f 612=over 4
613
ebc77b53 614=item Arguments: @args
66d9ef6b 615
d601dc88 616=item Return Value: $new_schema
27f01d1f 617
618=back
82b01c38 619
620Instantiates a new Storage object of type
621L<DBIx::Class::Schema/"storage_type"> and passes the arguments to
85f78622 622$storage->connect_info. Sets the connection in-place on the schema.
623
624See L<DBIx::Class::Storage::DBI/"connect_info"> for DBI-specific syntax,
625or L<DBIx::Class::Storage> in general.
66d9ef6b 626
627=cut
628
629sub connection {
630 my ($self, @info) = @_;
e59d3e5b 631 return $self if !@info && $self->storage;
1e10a11d 632 my $storage_class = $self->storage_type;
633 $storage_class = 'DBIx::Class::Storage'.$storage_class
634 if $storage_class =~ m/^::/;
8ef144ff 635 eval "require ${storage_class};";
bc0c9800 636 $self->throw_exception(
637 "No arguments to load_classes and couldn't load ${storage_class} ($@)"
638 ) if $@;
82cc0386 639 my $storage = $storage_class->new($self);
66d9ef6b 640 $storage->connect_info(\@info);
641 $self->storage($storage);
642 return $self;
643}
644
87c4e602 645=head2 connect
646
27f01d1f 647=over 4
648
ebc77b53 649=item Arguments: @info
66d9ef6b 650
d601dc88 651=item Return Value: $new_schema
27f01d1f 652
653=back
82b01c38 654
655This is a convenience method. It is equivalent to calling
656$schema->clone->connection(@info). See L</connection> and L</clone> for more
657information.
66d9ef6b 658
659=cut
660
08b515f1 661sub connect { shift->clone->connection(@_) }
662
4012acd8 663=head2 txn_do
08b515f1 664
4012acd8 665=over 4
08b515f1 666
4012acd8 667=item Arguments: C<$coderef>, @coderef_args?
08b515f1 668
4012acd8 669=item Return Value: The return value of $coderef
08b515f1 670
4012acd8 671=back
08b515f1 672
4012acd8 673Executes C<$coderef> with (optional) arguments C<@coderef_args> atomically,
674returning its result (if any). Equivalent to calling $schema->storage->txn_do.
675See L<DBIx::Class::Storage/"txn_do"> for more information.
08b515f1 676
4012acd8 677This interface is preferred over using the individual methods L</txn_begin>,
678L</txn_commit>, and L</txn_rollback> below.
08b515f1 679
4012acd8 680=cut
08b515f1 681
4012acd8 682sub txn_do {
683 my $self = shift;
08b515f1 684
4012acd8 685 $self->storage or $self->throw_exception
686 ('txn_do called on $schema without storage');
08b515f1 687
4012acd8 688 $self->storage->txn_do(@_);
689}
08b515f1 690
4012acd8 691=head2 txn_begin
a62cf8d4 692
4012acd8 693Begins a transaction (does nothing if AutoCommit is off). Equivalent to
694calling $schema->storage->txn_begin. See
695L<DBIx::Class::Storage::DBI/"txn_begin"> for more information.
27f01d1f 696
4012acd8 697=cut
82b01c38 698
4012acd8 699sub txn_begin {
700 my $self = shift;
27f01d1f 701
4012acd8 702 $self->storage or $self->throw_exception
703 ('txn_begin called on $schema without storage');
a62cf8d4 704
4012acd8 705 $self->storage->txn_begin;
706}
a62cf8d4 707
4012acd8 708=head2 txn_commit
a62cf8d4 709
4012acd8 710Commits the current transaction. Equivalent to calling
711$schema->storage->txn_commit. See L<DBIx::Class::Storage::DBI/"txn_commit">
712for more information.
a62cf8d4 713
4012acd8 714=cut
a62cf8d4 715
4012acd8 716sub txn_commit {
717 my $self = shift;
a62cf8d4 718
4012acd8 719 $self->storage or $self->throw_exception
720 ('txn_commit called on $schema without storage');
a62cf8d4 721
4012acd8 722 $self->storage->txn_commit;
723}
70634260 724
4012acd8 725=head2 txn_rollback
a62cf8d4 726
4012acd8 727Rolls back the current transaction. Equivalent to calling
728$schema->storage->txn_rollback. See
729L<DBIx::Class::Storage::DBI/"txn_rollback"> for more information.
a62cf8d4 730
731=cut
732
4012acd8 733sub txn_rollback {
734 my $self = shift;
a62cf8d4 735
19630353 736 $self->storage or $self->throw_exception
4012acd8 737 ('txn_rollback called on $schema without storage');
a62cf8d4 738
4012acd8 739 $self->storage->txn_rollback;
a62cf8d4 740}
741
66d9ef6b 742=head2 clone
743
27f01d1f 744=over 4
745
d601dc88 746=item Return Value: $new_schema
27f01d1f 747
748=back
82b01c38 749
66d9ef6b 750Clones the schema and its associated result_source objects and returns the
751copy.
752
753=cut
754
755sub clone {
756 my ($self) = @_;
04786a4c 757 my $clone = { (ref $self ? %$self : ()) };
758 bless $clone, (ref $self || $self);
759
66d9ef6b 760 foreach my $moniker ($self->sources) {
761 my $source = $self->source($moniker);
762 my $new = $source->new($source);
763 $clone->register_source($moniker => $new);
764 }
82cc0386 765 $clone->storage->set_schema($clone) if $clone->storage;
66d9ef6b 766 return $clone;
767}
768
87c4e602 769=head2 populate
770
27f01d1f 771=over 4
772
16c5f7d3 773=item Arguments: $source_name, \@data;
27f01d1f 774
775=back
a37a4697 776
16c5f7d3 777Pass this method a resultsource name, and an arrayref of
778arrayrefs. The arrayrefs should contain a list of column names,
779followed by one or many sets of matching data for the given columns.
780
781Each set of data is inserted into the database using
782L<DBIx::Class::ResultSet/create>, and a arrayref of the resulting row
783objects is returned.
82b01c38 784
785i.e.,
a37a4697 786
24d67825 787 $schema->populate('Artist', [
788 [ qw/artistid name/ ],
789 [ 1, 'Popular Band' ],
790 [ 2, 'Indie Band' ],
a62cf8d4 791 ...
792 ]);
a37a4697 793
794=cut
795
796sub populate {
797 my ($self, $name, $data) = @_;
798 my $rs = $self->resultset($name);
799 my @names = @{shift(@$data)};
84e3c114 800 my @created;
a37a4697 801 foreach my $item (@$data) {
802 my %create;
803 @create{@names} = @$item;
84e3c114 804 push(@created, $rs->create(\%create));
a37a4697 805 }
84e3c114 806 return @created;
a37a4697 807}
808
82cc0386 809=head2 exception_action
810
811=over 4
812
813=item Arguments: $code_reference
814
815=back
816
db5dc233 817If C<exception_action> is set for this class/object, L</throw_exception>
818will prefer to call this code reference with the exception as an argument,
819rather than its normal <croak> action.
820
821Your subroutine should probably just wrap the error in the exception
822object/class of your choosing and rethrow. If, against all sage advice,
823you'd like your C<exception_action> to suppress a particular exception
824completely, simply have it return true.
82cc0386 825
826Example:
827
828 package My::Schema;
829 use base qw/DBIx::Class::Schema/;
830 use My::ExceptionClass;
831 __PACKAGE__->exception_action(sub { My::ExceptionClass->throw(@_) });
832 __PACKAGE__->load_classes;
833
db5dc233 834 # or:
82cc0386 835 my $schema_obj = My::Schema->connect( .... );
836 $schema_obj->exception_action(sub { My::ExceptionClass->throw(@_) });
837
db5dc233 838 # suppress all exceptions, like a moron:
839 $schema_obj->exception_action(sub { 1 });
840
5160b401 841=head2 throw_exception
701da8c4 842
75d07914 843=over 4
82b01c38 844
ebc77b53 845=item Arguments: $message
82b01c38 846
847=back
848
849Throws an exception. Defaults to using L<Carp::Clan> to report errors from
db5dc233 850user's perspective. See L</exception_action> for details on overriding
851this method's behavior.
701da8c4 852
853=cut
854
855sub throw_exception {
82cc0386 856 my $self = shift;
db5dc233 857 croak @_ if !$self->exception_action || !$self->exception_action->(@_);
701da8c4 858}
859
ec6704d4 860=head2 deploy (EXPERIMENTAL)
1c339d71 861
82b01c38 862=over 4
863
6e73ac25 864=item Arguments: $sqlt_args, $dir
82b01c38 865
866=back
867
868Attempts to deploy the schema to the current storage using L<SQL::Translator>.
ec6704d4 869
870Note that this feature is currently EXPERIMENTAL and may not work correctly
871across all databases, or fully handle complex relationships.
1c339d71 872
51bace1c 873See L<SQL::Translator/METHODS> for a list of values for C<$sqlt_args>. The most
874common value for this would be C<< { add_drop_table => 1, } >> to have the SQL
875produced include a DROP TABLE statement for each table created.
876
1c339d71 877=cut
878
879sub deploy {
6e73ac25 880 my ($self, $sqltargs, $dir) = @_;
1c339d71 881 $self->throw_exception("Can't deploy without storage") unless $self->storage;
6e73ac25 882 $self->storage->deploy($self, undef, $sqltargs, $dir);
1c339d71 883}
884
c0f61310 885=head2 create_ddl_dir (EXPERIMENTAL)
886
887=over 4
888
889=item Arguments: \@databases, $version, $directory, $sqlt_args
890
891=back
892
893Creates an SQL file based on the Schema, for each of the specified
894database types, in the given directory.
895
896Note that this feature is currently EXPERIMENTAL and may not work correctly
897across all databases, or fully handle complex relationships.
898
899=cut
900
6e73ac25 901sub create_ddl_dir {
e673f011 902 my $self = shift;
903
904 $self->throw_exception("Can't create_ddl_dir without storage") unless $self->storage;
905 $self->storage->create_ddl_dir($self, @_);
906}
907
9b83fccd 908=head2 ddl_filename (EXPERIMENTAL)
909
910 my $filename = $table->ddl_filename($type, $dir, $version)
911
912Creates a filename for a SQL file based on the table class name. Not
913intended for direct end user use.
914
915=cut
916
6e73ac25 917sub ddl_filename {
e673f011 918 my ($self, $type, $dir, $version) = @_;
919
920 my $filename = ref($self);
9e7b9292 921 $filename =~ s/::/-/;
e673f011 922 $filename = "$dir$filename-$version-$type.sql";
923
924 return $filename;
925}
926
a02675cd 9271;
c2da098a 928
c2da098a 929=head1 AUTHORS
930
daec44b8 931Matt S. Trout <mst@shadowcatsystems.co.uk>
c2da098a 932
933=head1 LICENSE
934
935You may distribute this code under the same terms as Perl itself.
936
937=cut