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