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