Added standard arguments/return value to all docced methods.
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / ResultSource.pm
CommitLineData
9c992ba1 1package DBIx::Class::ResultSource;
2
3use strict;
4use warnings;
5
6use DBIx::Class::ResultSet;
aec3eff1 7use DBIx::Class::ResultSourceHandle;
701da8c4 8use Carp::Clan qw/^DBIx::Class/;
6da5894c 9use Storable;
10
9c992ba1 11use base qw/DBIx::Class/;
9c992ba1 12
aa1088bf 13__PACKAGE__->mk_group_accessors('simple' => qw/_ordered_columns
14 _columns _primaries _unique_constraints name resultset_attributes
acbe81cf 15 schema from _relationships column_info_from_storage source_info
aaf2403d 16 source_name/);
aa1088bf 17
fac560c2 18__PACKAGE__->mk_group_accessors('component_class' => qw/resultset_class
b0dd0e03 19 result_class/);
9c992ba1 20
75d07914 21=head1 NAME
9c992ba1 22
23DBIx::Class::ResultSource - Result source object
24
25=head1 SYNOPSIS
26
27=head1 DESCRIPTION
28
29A ResultSource is a component of a schema from which results can be directly
30retrieved, most usually a table (see L<DBIx::Class::ResultSource::Table>)
31
32=head1 METHODS
33
7eb4ecc8 34=pod
35
36=head2 new
37
38 $class->new();
39
40 $class->new({attribute_name => value});
41
42Creates a new ResultSource object. Not normally called directly by end users.
43
9c992ba1 44=cut
45
46sub new {
47 my ($class, $attrs) = @_;
48 $class = ref $class if ref $class;
04786a4c 49
6b051e14 50 my $new = bless { %{$attrs || {}} }, $class;
9c992ba1 51 $new->{resultset_class} ||= 'DBIx::Class::ResultSet';
5ac6a044 52 $new->{resultset_attributes} = { %{$new->{resultset_attributes} || {}} };
6da5894c 53 $new->{_ordered_columns} = [ @{$new->{_ordered_columns}||[]}];
54 $new->{_columns} = { %{$new->{_columns}||{}} };
55 $new->{_relationships} = { %{$new->{_relationships}||{}} };
9c992ba1 56 $new->{name} ||= "!!NAME NOT SET!!";
5afa2a15 57 $new->{_columns_info_loaded} ||= 0;
9c992ba1 58 return $new;
59}
60
988bf309 61=pod
62
a48e92d7 63=head2 source_info
64
65Stores a hashref of per-source metadata. No specific key names
66have yet been standardized, the examples below are purely hypothetical
67and don't actually accomplish anything on their own:
68
69 __PACKAGE__->source_info({
70 "_tablespace" => 'fast_disk_array_3',
71 "_engine" => 'InnoDB',
72 });
73
5ac6a044 74=head2 add_columns
75
391ccf38 76=over
77
78=item Arguments: @columns
79
80=item Return value: The ResultSource object
81
82=back
83
5ac6a044 84 $table->add_columns(qw/col1 col2 col3/);
85
86 $table->add_columns('col1' => \%col1_info, 'col2' => \%col2_info, ...);
87
2053ab2a 88Adds columns to the result source. If supplied key => hashref pairs, uses
89the hashref as the column_info for that column. Repeated calls of this
90method will add more columns, not replace them.
5ac6a044 91
5d9d9e87 92The column names given will be created as accessor methods on your
93L<DBIx::Class::Row> objects, you can change the name of the accessor
94by supplying an L</accessor> in the column_info hash.
95
2053ab2a 96The contents of the column_info are not set in stone. The following
97keys are currently recognised/used by DBIx::Class:
988bf309 98
99=over 4
100
75d07914 101=item accessor
988bf309 102
5d9d9e87 103Use this to set the name of the accessor method for this column. If unset,
988bf309 104the name of the column will be used.
105
106=item data_type
107
2053ab2a 108This contains the column type. It is automatically filled by the
988bf309 109L<SQL::Translator::Producer::DBIx::Class::File> producer, and the
2053ab2a 110L<DBIx::Class::Schema::Loader> module. If you do not enter a
988bf309 111data_type, DBIx::Class will attempt to retrieve it from the
2053ab2a 112database for you, using L<DBI>'s column_info method. The values of this
988bf309 113key are typically upper-cased.
114
2053ab2a 115Currently there is no standard set of values for the data_type. Use
116whatever your database supports.
988bf309 117
118=item size
119
120The length of your column, if it is a column type that can have a size
d7be2784 121restriction. This is currently only used by L<DBIx::Class::Schema/deploy>.
988bf309 122
123=item is_nullable
124
2053ab2a 125Set this to a true value for a columns that is allowed to contain
d7be2784 126NULL values. This is currently only used by L<DBIx::Class::Schema/deploy>.
988bf309 127
128=item is_auto_increment
129
2053ab2a 130Set this to a true value for a column whose value is somehow
131automatically set. This is used to determine which columns to empty
d7be2784 132when cloning objects using C<copy>. It is also used by
133L<DBIx::Class::Schema/deploy>.
988bf309 134
135=item is_foreign_key
136
2053ab2a 137Set this to a true value for a column that contains a key from a
d7be2784 138foreign table. This is currently only used by
139L<DBIx::Class::Schema/deploy>.
988bf309 140
141=item default_value
142
2053ab2a 143Set this to the default value which will be inserted into a column
144by the database. Can contain either a value or a function. This is
d7be2784 145currently only used by L<DBIx::Class::Schema/deploy>.
988bf309 146
147=item sequence
148
2053ab2a 149Set this on a primary key column to the name of the sequence used to
150generate a new key value. If not specified, L<DBIx::Class::PK::Auto>
151will attempt to retrieve the name of the sequence from the database
152automatically.
988bf309 153
838ef78d 154=item auto_nextval
155
156Set this to a true value for a column whose value is retrieved
157automatically from an oracle sequence. If you do not use an oracle
158trigger to get the nextval, you have to set sequence as well.
159
190615a7 160=item extra
d7be2784 161
162This is used by L<DBIx::Class::Schema/deploy> and L<SQL::Translator>
190615a7 163to add extra non-generic data to the column. For example: C<< extra
d7be2784 164=> { unsigned => 1} >> is used by the MySQL producer to set an integer
165column to unsigned. For more details, see
166L<SQL::Translator::Producer::MySQL>.
167
988bf309 168=back
169
5ac6a044 170=head2 add_column
171
391ccf38 172=over
173
174=item Arguments: $colname, [ \%columninfo ]
175
176=item Return value: 1/0 (true/false)
177
178=back
179
5ac6a044 180 $table->add_column('col' => \%info?);
181
391ccf38 182Add a single column and optional column info. Uses the same column
183info keys as L</add_columns>.
5ac6a044 184
185=cut
186
9c992ba1 187sub add_columns {
188 my ($self, @cols) = @_;
8e04bf91 189 $self->_ordered_columns(\@cols) unless $self->_ordered_columns;
002a359a 190
20518cb4 191 my @added;
192 my $columns = $self->_columns;
9c992ba1 193 while (my $col = shift @cols) {
8e04bf91 194 # If next entry is { ... } use that for the column info, if not
195 # use an empty hashref
30126ac7 196 my $column_info = ref $cols[0] ? shift(@cols) : {};
20518cb4 197 push(@added, $col) unless exists $columns->{$col};
20518cb4 198 $columns->{$col} = $column_info;
9c992ba1 199 }
20518cb4 200 push @{ $self->_ordered_columns }, @added;
30126ac7 201 return $self;
9c992ba1 202}
203
b25e9fa0 204sub add_column { shift->add_columns(@_); } # DO NOT CHANGE THIS TO GLOB
9c992ba1 205
3842b955 206=head2 has_column
207
391ccf38 208=over
209
210=item Arguments: $colname
211
212=item Return value: 1/0 (true/false)
213
214=back
215
216 if ($obj->has_column($colname)) { ... }
988bf309 217
2053ab2a 218Returns true if the source has a column of this name, false otherwise.
988bf309 219
220=cut
9c992ba1 221
222sub has_column {
223 my ($self, $column) = @_;
224 return exists $self->_columns->{$column};
225}
226
87c4e602 227=head2 column_info
9c992ba1 228
391ccf38 229=over
230
231=item Arguments: $colname
232
233=item Return value: Hashref of info
234
235=back
236
988bf309 237 my $info = $obj->column_info($col);
9c992ba1 238
391ccf38 239Returns the column metadata hashref for a column, as originally passed
240to L</add_columns>. See the description of L</add_columns> for information
241on the contents of the hashref.
9c992ba1 242
988bf309 243=cut
9c992ba1 244
245sub column_info {
246 my ($self, $column) = @_;
75d07914 247 $self->throw_exception("No such column $column")
701da8c4 248 unless exists $self->_columns->{$column};
5afa2a15 249 #warn $self->{_columns_info_loaded}, "\n";
75d07914 250 if ( ! $self->_columns->{$column}{data_type}
6eda9bcf 251 and $self->column_info_from_storage
75d07914 252 and ! $self->{_columns_info_loaded}
8e04bf91 253 and $self->schema and $self->storage )
254 {
255 $self->{_columns_info_loaded}++;
d51f93c8 256 my $info = {};
257 my $lc_info = {};
75d07914 258 # eval for the case of storage without table
955f1590 259 eval { $info = $self->storage->columns_info_for( $self->from ) };
8e04bf91 260 unless ($@) {
0b88a5bb 261 for my $realcol ( keys %{$info} ) {
262 $lc_info->{lc $realcol} = $info->{$realcol};
263 }
8e04bf91 264 foreach my $col ( keys %{$self->_columns} ) {
d51f93c8 265 $self->_columns->{$col} = {
266 %{ $self->_columns->{$col} },
267 %{ $info->{$col} || $lc_info->{lc $col} || {} }
268 };
a953d8d9 269 }
8e04bf91 270 }
a953d8d9 271 }
9c992ba1 272 return $self->_columns->{$column};
273}
274
d9916234 275=head2 column_info_from_storage
6eda9bcf 276
391ccf38 277=over
278
279=item Arguments: 1/0 (default: 0)
280
281=item Return value: 1/0
282
283=back
284
6eda9bcf 285Enables the on-demand automatic loading of the above column
c22c7625 286metadata from storage as neccesary. This is *deprecated*, and
287should not be used. It will be removed before 1.0.
6eda9bcf 288
d9916234 289 __PACKAGE__->column_info_from_storage(1);
6eda9bcf 290
9c992ba1 291=head2 columns
292
391ccf38 293=over
294
295=item Arguments: None
296
297=item Return value: Ordered list of column names
298
299=back
300
301 my @column_names = $source->columns;
20518cb4 302
391ccf38 303Returns all column names in the order they were declared to L</add_columns>.
87f0da6a 304
305=cut
9c992ba1 306
307sub columns {
8e04bf91 308 my $self = shift;
aa1088bf 309 $self->throw_exception(
310 "columns() is a read-only accessor, did you mean add_columns()?"
311 ) if (@_ > 1);
701da8c4 312 return @{$self->{_ordered_columns}||[]};
571dced3 313}
314
002a359a 315=head2 remove_columns
316
391ccf38 317=over
002a359a 318
391ccf38 319=item Arguments: @colnames
320
321=item Return value: undefined
322
323=back
324
325 $source->remove_columns(qw/col1 col2 col3/);
326
327Removes the given list of columns by name, from the result source.
328
329B<Warning>: Removing a column that is also used in the sources primary
330key, or in one of the sources unique constraints, B<will> result in a
331broken result source.
002a359a 332
333=head2 remove_column
334
391ccf38 335=over
336
337=item Arguments: $colname
338
339=item Return value: undefined
340
341=back
002a359a 342
391ccf38 343 $source->remove_column('col');
344
345Remove a single column by name from the result source, similar to
346L</remove_columns>.
347
348B<Warning>: Removing a column that is also used in the sources primary
349key, or in one of the sources unique constraints, B<will> result in a
350broken result source.
002a359a 351
352=cut
353
354sub remove_columns {
355 my ($self, @cols) = @_;
356
357 return unless $self->_ordered_columns;
358
359 my $columns = $self->_columns;
360 my @remaining;
361
362 foreach my $col (@{$self->_ordered_columns}) {
363 push @remaining, $col unless grep(/$col/, @cols);
364 }
365
366 foreach (@cols) {
a918d901 367 delete $columns->{$_};
002a359a 368 };
369
370 $self->_ordered_columns(\@remaining);
371}
372
b25e9fa0 373sub remove_column { shift->remove_columns(@_); } # DO NOT CHANGE THIS TO GLOB
002a359a 374
87c4e602 375=head2 set_primary_key
376
27f01d1f 377=over 4
378
ebc77b53 379=item Arguments: @cols
27f01d1f 380
391ccf38 381=item Return value: undefined
382
27f01d1f 383=back
87f0da6a 384
9c992ba1 385Defines one or more columns as primary key for this source. Should be
391ccf38 386called after L</add_columns>.
87f0da6a 387
391ccf38 388Additionally, defines a L<unique constraint|add_unique_constraint>
389named C<primary>.
87f0da6a 390
988bf309 391The primary key columns are used by L<DBIx::Class::PK::Auto> to
75d07914 392retrieve automatically created values from the database.
988bf309 393
87f0da6a 394=cut
9c992ba1 395
396sub set_primary_key {
397 my ($self, @cols) = @_;
398 # check if primary key columns are valid columns
8e04bf91 399 foreach my $col (@cols) {
400 $self->throw_exception("No such column $col on table " . $self->name)
401 unless $self->has_column($col);
9c992ba1 402 }
403 $self->_primaries(\@cols);
87f0da6a 404
405 $self->add_unique_constraint(primary => \@cols);
9c992ba1 406}
407
87f0da6a 408=head2 primary_columns
409
391ccf38 410=over 4
411
412=item Arguments: None
413
414=item Return value: Ordered list of primary column names
415
416=back
417
418Read-only accessor which returns the list of primary keys, supplied by
419L</set_primary_key>.
30126ac7 420
87f0da6a 421=cut
9c992ba1 422
423sub primary_columns {
424 return @{shift->_primaries||[]};
425}
426
87f0da6a 427=head2 add_unique_constraint
428
391ccf38 429=over 4
430
431=item Arguments: [ $name ], \@colnames
432
433=item Return value: undefined
434
435=back
436
87f0da6a 437Declare a unique constraint on this source. Call once for each unique
58b5bb8c 438constraint.
27f01d1f 439
440 # For UNIQUE (column1, column2)
441 __PACKAGE__->add_unique_constraint(
442 constraint_name => [ qw/column1 column2/ ],
443 );
87f0da6a 444
368a5228 445Alternatively, you can specify only the columns:
446
447 __PACKAGE__->add_unique_constraint([ qw/column1 column2/ ]);
448
449This will result in a unique constraint named C<table_column1_column2>, where
450C<table> is replaced with the table name.
451
58b5bb8c 452Unique constraints are used, for example, when you call
453L<DBIx::Class::ResultSet/find>. Only columns in the constraint are searched.
454
391ccf38 455Throws an error if any of the given column names do not yet exist on
456the result source.
457
87f0da6a 458=cut
459
460sub add_unique_constraint {
368a5228 461 my $self = shift;
462 my $cols = pop @_;
463 my $name = shift;
464
465 $name ||= $self->name_unique_constraint($cols);
87f0da6a 466
8e04bf91 467 foreach my $col (@$cols) {
468 $self->throw_exception("No such column $col on table " . $self->name)
469 unless $self->has_column($col);
87f0da6a 470 }
471
472 my %unique_constraints = $self->unique_constraints;
473 $unique_constraints{$name} = $cols;
474 $self->_unique_constraints(\%unique_constraints);
475}
476
d9c74322 477=head2 name_unique_constraint
368a5228 478
391ccf38 479=over 4
480
481=item Arguments: @colnames
482
483=item Return value: Constraint name
484
485=back
486
487 $source->table('mytable');
488 $source->name_unique_constraint('col1', 'col2');
489 # returns
490 'mytable_col1_col2'
491
492Return a name for a unique constraint containing the specified
493columns. The name is created by joining the table name and each column
494name, using an underscore character.
368a5228 495
496For example, a constraint on a table named C<cd> containing the columns
497C<artist> and C<title> would result in a constraint name of C<cd_artist_title>.
498
391ccf38 499This is used by L</add_unique_constraint> if you do not specify the
500optional constraint name.
501
368a5228 502=cut
503
504sub name_unique_constraint {
505 my ($self, $cols) = @_;
506
507 return join '_', $self->name, @$cols;
508}
509
87f0da6a 510=head2 unique_constraints
511
391ccf38 512=over 4
513
514=item Arguments: None
515
516=item Return value: Hash of unique constraint data
517
518=back
519
520 $source->unique_constraints();
521
522Read-only accessor which returns a hash of unique constraints on this source.
523
524The hash is keyed by constraint name, and contains an arrayref of
525column names as values.
87f0da6a 526
527=cut
528
529sub unique_constraints {
530 return %{shift->_unique_constraints||{}};
531}
532
e6a0e17c 533=head2 unique_constraint_names
534
391ccf38 535=over 4
536
537=item Arguments: None
538
539=item Return value: Unique constraint names
540
541=back
542
543 $source->unique_constraint_names();
544
e6a0e17c 545Returns the list of unique constraint names defined on this source.
546
547=cut
548
549sub unique_constraint_names {
550 my ($self) = @_;
551
552 my %unique_constraints = $self->unique_constraints;
553
554 return keys %unique_constraints;
555}
556
557=head2 unique_constraint_columns
558
391ccf38 559=over 4
560
561=item Arguments: $constraintname
562
563=item Return value: List of constraint columns
564
565=back
566
567 $source->unique_constraint_columns('myconstraint');
568
e6a0e17c 569Returns the list of columns that make up the specified unique constraint.
570
571=cut
572
573sub unique_constraint_columns {
574 my ($self, $constraint_name) = @_;
575
576 my %unique_constraints = $self->unique_constraints;
577
578 $self->throw_exception(
579 "Unknown unique constraint $constraint_name on '" . $self->name . "'"
580 ) unless exists $unique_constraints{$constraint_name};
581
582 return @{ $unique_constraints{$constraint_name} };
583}
584
9c992ba1 585=head2 from
586
391ccf38 587=over 4
588
589=item Arguments: None
590
591=item Return value: FROM clause
592
593=back
594
595 my $from_clause = $source->from();
596
9c992ba1 597Returns an expression of the source to be supplied to storage to specify
2053ab2a 598retrieval from this source. In the case of a database, the required FROM
599clause contents.
9c992ba1 600
f9b7bd6e 601=head2 schema
602
391ccf38 603=over 4
604
605=item Arguments: None
606
607=item Return value: A schema object
608
609=back
610
611 my $schema = $source->schema();
612
f9b7bd6e 613Returns the L<DBIx::Class::Schema> object that this result source
391ccf38 614belongs to.
9c992ba1 615
616=head2 storage
617
391ccf38 618=over 4
619
620=item Arguments: None
621
622=item Return value: A Storage object
623
624=back
625
626 $source->storage->debug(1);
627
75d07914 628Returns the storage handle for the current schema.
988bf309 629
630See also: L<DBIx::Class::Storage>
9c992ba1 631
632=cut
633
634sub storage { shift->schema->storage; }
635
8452e496 636=head2 add_relationship
637
391ccf38 638=over 4
639
640=item Arguments: $relname, $related_source_name, \%cond, [ \%attrs ]
641
642=item Return value: 1/true if it succeeded
643
644=back
645
8452e496 646 $source->add_relationship('relname', 'related_source', $cond, $attrs);
647
391ccf38 648L<DBIx::Class::Relationship> describes a series of methods which
649create pre-defined useful types of relationships. Look there first
650before using this method directly.
651
24d67825 652The relationship name can be arbitrary, but must be unique for each
653relationship attached to this result source. 'related_source' should
654be the name with which the related result source was registered with
655the current schema. For example:
8452e496 656
24d67825 657 $schema->source('Book')->add_relationship('reviews', 'Review', {
658 'foreign.book_id' => 'self.id',
659 });
660
2053ab2a 661The condition C<$cond> needs to be an L<SQL::Abstract>-style
24d67825 662representation of the join between the tables. For example, if you're
391ccf38 663creating a relation from Author to Book,
988bf309 664
665 { 'foreign.author_id' => 'self.id' }
666
667will result in the JOIN clause
668
669 author me JOIN book foreign ON foreign.author_id = me.id
670
8452e496 671You can specify as many foreign => self mappings as necessary.
672
988bf309 673Valid attributes are as follows:
674
675=over 4
676
677=item join_type
678
679Explicitly specifies the type of join to use in the relationship. Any
680SQL join type is valid, e.g. C<LEFT> or C<RIGHT>. It will be placed in
681the SQL command immediately before C<JOIN>.
682
683=item proxy
684
24d67825 685An arrayref containing a list of accessors in the foreign class to proxy in
686the main class. If, for example, you do the following:
002a359a 687
24d67825 688 CD->might_have(liner_notes => 'LinerNotes', undef, {
689 proxy => [ qw/notes/ ],
690 });
002a359a 691
24d67825 692Then, assuming LinerNotes has an accessor named notes, you can do:
988bf309 693
24d67825 694 my $cd = CD->find(1);
2053ab2a 695 # set notes -- LinerNotes object is created if it doesn't exist
696 $cd->notes('Notes go here');
988bf309 697
698=item accessor
699
700Specifies the type of accessor that should be created for the
75d07914 701relationship. Valid values are C<single> (for when there is only a single
702related object), C<multi> (when there can be many), and C<filter> (for
703when there is a single related object, but you also want the relationship
704accessor to double as a column accessor). For C<multi> accessors, an
705add_to_* method is also created, which calls C<create_related> for the
988bf309 706relationship.
707
8452e496 708=back
709
391ccf38 710Throws an exception if the condition is improperly supplied, or cannot
711be resolved using L</resolve_join>.
712
8452e496 713=cut
714
715sub add_relationship {
716 my ($self, $rel, $f_source_name, $cond, $attrs) = @_;
27f01d1f 717 $self->throw_exception("Can't create relationship without join condition")
718 unless $cond;
8452e496 719 $attrs ||= {};
87772e46 720
eba322a7 721 # Check foreign and self are right in cond
722 if ( (ref $cond ||'') eq 'HASH') {
723 for (keys %$cond) {
724 $self->throw_exception("Keys of condition should be of form 'foreign.col', not '$_'")
725 if /\./ && !/^foreign\./;
726 }
727 }
728
8452e496 729 my %rels = %{ $self->_relationships };
730 $rels{$rel} = { class => $f_source_name,
87772e46 731 source => $f_source_name,
8452e496 732 cond => $cond,
733 attrs => $attrs };
734 $self->_relationships(\%rels);
735
30126ac7 736 return $self;
87772e46 737
953a18ef 738 # XXX disabled. doesn't work properly currently. skip in tests.
739
8452e496 740 my $f_source = $self->schema->source($f_source_name);
741 unless ($f_source) {
c037c03a 742 $self->ensure_class_loaded($f_source_name);
8452e496 743 $f_source = $f_source_name->result_source;
87772e46 744 #my $s_class = ref($self->schema);
745 #$f_source_name =~ m/^${s_class}::(.*)$/;
746 #$self->schema->register_class(($1 || $f_source_name), $f_source_name);
747 #$f_source = $self->schema->source($f_source_name);
8452e496 748 }
749 return unless $f_source; # Can't test rel without f_source
750
751 eval { $self->resolve_join($rel, 'me') };
752
753 if ($@) { # If the resolve failed, back out and re-throw the error
75d07914 754 delete $rels{$rel}; #
8452e496 755 $self->_relationships(\%rels);
701da8c4 756 $self->throw_exception("Error creating relationship $rel: $@");
8452e496 757 }
758 1;
759}
760
87c4e602 761=head2 relationships
8452e496 762
391ccf38 763=over 4
764
765=item Arguments: None
766
767=item Return value: List of relationship names
768
769=back
770
771 my @relnames = $source->relationships();
772
2053ab2a 773Returns all relationship names for this source.
8452e496 774
775=cut
776
777sub relationships {
778 return keys %{shift->_relationships};
779}
780
87c4e602 781=head2 relationship_info
782
27f01d1f 783=over 4
784
ebc77b53 785=item Arguments: $relname
27f01d1f 786
391ccf38 787=item Return value: Hashref of relation data,
788
27f01d1f 789=back
8452e496 790
2053ab2a 791Returns a hash of relationship information for the specified relationship
391ccf38 792name. The keys/values are as specified for L</add_relationship>.
8452e496 793
794=cut
795
796sub relationship_info {
797 my ($self, $rel) = @_;
798 return $self->_relationships->{$rel};
75d07914 799}
8452e496 800
87c4e602 801=head2 has_relationship
802
27f01d1f 803=over 4
804
ebc77b53 805=item Arguments: $rel
27f01d1f 806
391ccf38 807=item Return value: 1/0 (true/false)
808
27f01d1f 809=back
953a18ef 810
2053ab2a 811Returns true if the source has a relationship of this name, false otherwise.
988bf309 812
813=cut
953a18ef 814
815sub has_relationship {
816 my ($self, $rel) = @_;
817 return exists $self->_relationships->{$rel};
818}
819
de60a93d 820=head2 reverse_relationship_info
821
822=over 4
823
824=item Arguments: $relname
825
391ccf38 826=item Return value: Hashref of relationship data
827
de60a93d 828=back
829
391ccf38 830Looks through all the relationships on the source this relationship
831points to, looking for one whose condition is the reverse of the
832condition on this relationship.
833
834A common use of this is to find the name of the C<belongs_to> relation
835opposing a C<has_many> relation. For definition of these look in
836L<DBIx::Class::Relationship>.
837
838The returned hashref is keyed by the name of the opposing
839relationship, and contains it's data in the same manner as
840L</relationship_info>.
de60a93d 841
842=cut
843
844sub reverse_relationship_info {
845 my ($self, $rel) = @_;
846 my $rel_info = $self->relationship_info($rel);
847 my $ret = {};
848
849 return $ret unless ((ref $rel_info->{cond}) eq 'HASH');
850
851 my @cond = keys(%{$rel_info->{cond}});
852 my @refkeys = map {/^\w+\.(\w+)$/} @cond;
853 my @keys = map {$rel_info->{cond}->{$_} =~ /^\w+\.(\w+)$/} @cond;
bab77431 854
de60a93d 855 # Get the related result source for this relationship
856 my $othertable = $self->related_source($rel);
857
858 # Get all the relationships for that source that related to this source
859 # whose foreign column set are our self columns on $rel and whose self
bab77431 860 # columns are our foreign columns on $rel.
de60a93d 861 my @otherrels = $othertable->relationships();
862 my $otherrelationship;
863 foreach my $otherrel (@otherrels) {
864 my $otherrel_info = $othertable->relationship_info($otherrel);
865
866 my $back = $othertable->related_source($otherrel);
f3fb2641 867 next unless $back->source_name eq $self->source_name;
de60a93d 868
869 my @othertestconds;
870
871 if (ref $otherrel_info->{cond} eq 'HASH') {
872 @othertestconds = ($otherrel_info->{cond});
873 }
874 elsif (ref $otherrel_info->{cond} eq 'ARRAY') {
875 @othertestconds = @{$otherrel_info->{cond}};
876 }
877 else {
878 next;
879 }
880
881 foreach my $othercond (@othertestconds) {
882 my @other_cond = keys(%$othercond);
883 my @other_refkeys = map {/^\w+\.(\w+)$/} @other_cond;
884 my @other_keys = map {$othercond->{$_} =~ /^\w+\.(\w+)$/} @other_cond;
bab77431 885 next if (!$self->compare_relationship_keys(\@refkeys, \@other_keys) ||
de60a93d 886 !$self->compare_relationship_keys(\@other_refkeys, \@keys));
887 $ret->{$otherrel} = $otherrel_info;
888 }
889 }
890 return $ret;
891}
892
893=head2 compare_relationship_keys
894
895=over 4
896
391ccf38 897=item Arguments: \@keys1, \@keys2
898
899=item Return value: 1/0 (true/false)
de60a93d 900
901=back
902
903Returns true if both sets of keynames are the same, false otherwise.
904
905=cut
906
907sub compare_relationship_keys {
908 my ($self, $keys1, $keys2) = @_;
909
910 # Make sure every keys1 is in keys2
911 my $found;
912 foreach my $key (@$keys1) {
913 $found = 0;
914 foreach my $prim (@$keys2) {
915 if ($prim eq $key) {
916 $found = 1;
917 last;
918 }
919 }
920 last unless $found;
921 }
922
923 # Make sure every key2 is in key1
924 if ($found) {
925 foreach my $prim (@$keys2) {
926 $found = 0;
927 foreach my $key (@$keys1) {
928 if ($prim eq $key) {
929 $found = 1;
930 last;
931 }
932 }
933 last unless $found;
934 }
935 }
936
937 return $found;
938}
939
87c4e602 940=head2 resolve_join
941
27f01d1f 942=over 4
943
ebc77b53 944=item Arguments: $relation
27f01d1f 945
391ccf38 946=item Return value: Join condition arrayref
947
27f01d1f 948=back
8452e496 949
2053ab2a 950Returns the join structure required for the related result source.
8452e496 951
952=cut
953
954sub resolve_join {
24010dd8 955 my ($self, $join, $alias, $seen, $force_left) = @_;
489709af 956 $seen ||= {};
24010dd8 957 $force_left ||= { force => 0 };
87772e46 958 if (ref $join eq 'ARRAY') {
489709af 959 return map { $self->resolve_join($_, $alias, $seen) } @$join;
87772e46 960 } elsif (ref $join eq 'HASH') {
489709af 961 return
887ce227 962 map {
963 my $as = ($seen->{$_} ? $_.'_'.($seen->{$_}+1) : $_);
24010dd8 964 local $force_left->{force};
965 (
966 $self->resolve_join($_, $alias, $seen, $force_left),
967 $self->related_source($_)->resolve_join(
968 $join->{$_}, $as, $seen, $force_left
969 )
970 );
887ce227 971 } keys %$join;
87772e46 972 } elsif (ref $join) {
701da8c4 973 $self->throw_exception("No idea how to resolve join reftype ".ref $join);
87772e46 974 } else {
489709af 975 my $count = ++$seen->{$join};
976 #use Data::Dumper; warn Dumper($seen);
977 my $as = ($count > 1 ? "${join}_${count}" : $join);
3842b955 978 my $rel_info = $self->relationship_info($join);
701da8c4 979 $self->throw_exception("No such relationship ${join}") unless $rel_info;
24010dd8 980 my $type;
981 if ($force_left->{force}) {
982 $type = 'left';
983 } else {
984 $type = $rel_info->{attrs}{join_type} || '';
985 $force_left->{force} = 1 if lc($type) eq 'left';
986 }
489709af 987 return [ { $as => $self->related_source($join)->from,
953a18ef 988 -join_type => $type },
489709af 989 $self->resolve_condition($rel_info->{cond}, $as, $alias) ];
953a18ef 990 }
991}
992
370f2ba2 993=head2 pk_depends_on
994
995=over 4
996
997=item Arguments: $relname, $rel_data
998
391ccf38 999=item Return value: 1/0 (true/false)
1000
370f2ba2 1001=back
1002
1003Determines whether a relation is dependent on an object from this source
1004having already been inserted. Takes the name of the relationship and a
1005hashref of columns of the related object.
1006
1007=cut
1008
1009sub pk_depends_on {
1010 my ($self, $relname, $rel_data) = @_;
1011 my $cond = $self->relationship_info($relname)->{cond};
1012
1013 return 0 unless ref($cond) eq 'HASH';
1014
1015 # map { foreign.foo => 'self.bar' } to { bar => 'foo' }
1016
1017 my $keyhash = { map { my $x = $_; $x =~ s/.*\.//; $x; } reverse %$cond };
1018
1019 # assume anything that references our PK probably is dependent on us
1020 # rather than vice versa, unless the far side is (a) defined or (b)
1021 # auto-increment
1022
1023 my $rel_source = $self->related_source($relname);
1024
1025 foreach my $p ($self->primary_columns) {
1026 if (exists $keyhash->{$p}) {
1027 unless (defined($rel_data->{$keyhash->{$p}})
1028 || $rel_source->column_info($keyhash->{$p})
1029 ->{is_auto_increment}) {
1030 return 0;
1031 }
1032 }
1033 }
1034
1035 return 1;
1036}
1037
87c4e602 1038=head2 resolve_condition
1039
27f01d1f 1040=over 4
1041
ebc77b53 1042=item Arguments: $cond, $as, $alias|$object
27f01d1f 1043
1044=back
953a18ef 1045
3842b955 1046Resolves the passed condition to a concrete query fragment. If given an alias,
953a18ef 1047returns a join condition; if given an object, inverts that object to produce
1048a related conditional from that object.
1049
1050=cut
1051
8c368cf3 1052our $UNRESOLVABLE_CONDITION = \'1 = 0';
1053
953a18ef 1054sub resolve_condition {
489709af 1055 my ($self, $cond, $as, $for) = @_;
953a18ef 1056 #warn %$cond;
1057 if (ref $cond eq 'HASH') {
1058 my %ret;
bd054cb4 1059 foreach my $k (keys %{$cond}) {
1060 my $v = $cond->{$k};
953a18ef 1061 # XXX should probably check these are valid columns
27f01d1f 1062 $k =~ s/^foreign\.// ||
75d07914 1063 $self->throw_exception("Invalid rel cond key ${k}");
27f01d1f 1064 $v =~ s/^self\.// ||
75d07914 1065 $self->throw_exception("Invalid rel cond val ${v}");
953a18ef 1066 if (ref $for) { # Object
3842b955 1067 #warn "$self $k $for $v";
370f2ba2 1068 unless ($for->has_column_loaded($v)) {
1069 if ($for->in_storage) {
6bf6ba2f 1070 $self->throw_exception("Column ${v} not loaded on ${for} trying to resolve relationship");
370f2ba2 1071 }
68f3b0dd 1072 return $UNRESOLVABLE_CONDITION;
370f2ba2 1073 }
1074 $ret{$k} = $for->get_column($v);
1075 #$ret{$k} = $for->get_column($v) if $for->has_column_loaded($v);
3842b955 1076 #warn %ret;
2c037e6b 1077 } elsif (!defined $for) { # undef, i.e. "no object"
1078 $ret{$k} = undef;
2ec8e594 1079 } elsif (ref $as eq 'HASH') { # reverse hashref
1080 $ret{$v} = $as->{$k};
fde6e28e 1081 } elsif (ref $as) { # reverse object
1082 $ret{$v} = $as->get_column($k);
2c037e6b 1083 } elsif (!defined $as) { # undef, i.e. "no reverse object"
1084 $ret{$v} = undef;
953a18ef 1085 } else {
489709af 1086 $ret{"${as}.${k}"} = "${for}.${v}";
953a18ef 1087 }
953a18ef 1088 }
1089 return \%ret;
5efe4c79 1090 } elsif (ref $cond eq 'ARRAY') {
489709af 1091 return [ map { $self->resolve_condition($_, $as, $for) } @$cond ];
953a18ef 1092 } else {
1093 die("Can't handle this yet :(");
87772e46 1094 }
1095}
1096
87c4e602 1097=head2 resolve_prefetch
1098
27f01d1f 1099=over 4
1100
ebc77b53 1101=item Arguments: hashref/arrayref/scalar
27f01d1f 1102
1103=back
988bf309 1104
b3e8ac9b 1105Accepts one or more relationships for the current source and returns an
1106array of column names for each of those relationships. Column names are
1107prefixed relative to the current source, in accordance with where they appear
1108in the supplied relationships. Examples:
1109
5ac6a044 1110 my $source = $schema->resultset('Tag')->source;
b3e8ac9b 1111 @columns = $source->resolve_prefetch( { cd => 'artist' } );
1112
1113 # @columns =
1114 #(
1115 # 'cd.cdid',
1116 # 'cd.artist',
1117 # 'cd.title',
1118 # 'cd.year',
1119 # 'cd.artist.artistid',
1120 # 'cd.artist.name'
1121 #)
1122
1123 @columns = $source->resolve_prefetch( qw[/ cd /] );
1124
1125 # @columns =
1126 #(
1127 # 'cd.cdid',
1128 # 'cd.artist',
1129 # 'cd.title',
1130 # 'cd.year'
1131 #)
1132
1133 $source = $schema->resultset('CD')->source;
1134 @columns = $source->resolve_prefetch( qw[/ artist producer /] );
1135
1136 # @columns =
1137 #(
1138 # 'artist.artistid',
1139 # 'artist.name',
1140 # 'producer.producerid',
1141 # 'producer.name'
75d07914 1142 #)
988bf309 1143
b3e8ac9b 1144=cut
1145
1146sub resolve_prefetch {
0f66a01b 1147 my ($self, $pre, $alias, $seen, $order, $collapse) = @_;
489709af 1148 $seen ||= {};
b3e8ac9b 1149 #$alias ||= $self->name;
1150 #warn $alias, Dumper $pre;
1151 if( ref $pre eq 'ARRAY' ) {
0f66a01b 1152 return
1153 map { $self->resolve_prefetch( $_, $alias, $seen, $order, $collapse ) }
1154 @$pre;
b3e8ac9b 1155 }
1156 elsif( ref $pre eq 'HASH' ) {
1157 my @ret =
1158 map {
0f66a01b 1159 $self->resolve_prefetch($_, $alias, $seen, $order, $collapse),
489709af 1160 $self->related_source($_)->resolve_prefetch(
0f66a01b 1161 $pre->{$_}, "${alias}.$_", $seen, $order, $collapse)
1162 } keys %$pre;
b3e8ac9b 1163 #die Dumper \@ret;
1164 return @ret;
1165 }
1166 elsif( ref $pre ) {
a86b1efe 1167 $self->throw_exception(
1168 "don't know how to resolve prefetch reftype ".ref($pre));
b3e8ac9b 1169 }
1170 else {
489709af 1171 my $count = ++$seen->{$pre};
1172 my $as = ($count > 1 ? "${pre}_${count}" : $pre);
b3e8ac9b 1173 my $rel_info = $self->relationship_info( $pre );
a86b1efe 1174 $self->throw_exception( $self->name . " has no such relationship '$pre'" )
1175 unless $rel_info;
37f23589 1176 my $as_prefix = ($alias =~ /^.*?\.(.+)$/ ? $1.'.' : '');
a86b1efe 1177 my $rel_source = $self->related_source($pre);
0f66a01b 1178
1179 if (exists $rel_info->{attrs}{accessor}
1180 && $rel_info->{attrs}{accessor} eq 'multi') {
1181 $self->throw_exception(
1182 "Can't prefetch has_many ${pre} (join cond too complex)")
1183 unless ref($rel_info->{cond}) eq 'HASH';
cb136e67 1184 my $dots = @{[$as_prefix =~ m/\./g]} + 1; # +1 to match the ".${as_prefix}"
1185 if (my ($fail) = grep { @{[$_ =~ m/\./g]} == $dots }
1186 keys %{$collapse}) {
1187 my ($last) = ($fail =~ /([^\.]+)$/);
616b461d 1188 carp (
1189 "Prefetching multiple has_many rels ${last} and ${pre} "
1190 .(length($as_prefix)
1191 ? "at the same level (${as_prefix}) "
1192 : "at top level "
1193 )
1194 . 'will currently disrupt both the functionality of $rs->count(), '
1195 . 'and the amount of objects retrievable via $rs->next(). '
1196 . 'Use at your own risk.'
1197 );
cb136e67 1198 }
b25e9fa0 1199 #my @col = map { (/^self\.(.+)$/ ? ("${as_prefix}.$1") : ()); }
1200 # values %{$rel_info->{cond}};
1201 $collapse->{".${as_prefix}${pre}"} = [ $rel_source->primary_columns ];
1202 # action at a distance. prepending the '.' allows simpler code
1203 # in ResultSet->_collapse_result
37f23589 1204 my @key = map { (/^foreign\.(.+)$/ ? ($1) : ()); }
0f66a01b 1205 keys %{$rel_info->{cond}};
5a5bec6c 1206 my @ord = (ref($rel_info->{attrs}{order_by}) eq 'ARRAY'
1207 ? @{$rel_info->{attrs}{order_by}}
1208 : (defined $rel_info->{attrs}{order_by}
1209 ? ($rel_info->{attrs}{order_by})
1210 : ()));
1211 push(@$order, map { "${as}.$_" } (@key, @ord));
0f66a01b 1212 }
1213
489709af 1214 return map { [ "${as}.$_", "${as_prefix}${pre}.$_", ] }
a86b1efe 1215 $rel_source->columns;
b3e8ac9b 1216 #warn $alias, Dumper (\@ret);
489709af 1217 #return @ret;
b3e8ac9b 1218 }
1219}
953a18ef 1220
87c4e602 1221=head2 related_source
1222
27f01d1f 1223=over 4
1224
ebc77b53 1225=item Arguments: $relname
27f01d1f 1226
391ccf38 1227=item Return value: $source
1228
27f01d1f 1229=back
87772e46 1230
2053ab2a 1231Returns the result source object for the given relationship.
87772e46 1232
1233=cut
1234
1235sub related_source {
1236 my ($self, $rel) = @_;
aea52c85 1237 if( !$self->has_relationship( $rel ) ) {
701da8c4 1238 $self->throw_exception("No such relationship '$rel'");
aea52c85 1239 }
87772e46 1240 return $self->schema->source($self->relationship_info($rel)->{source});
8452e496 1241}
1242
77254782 1243=head2 related_class
1244
27f01d1f 1245=over 4
1246
ebc77b53 1247=item Arguments: $relname
27f01d1f 1248
391ccf38 1249=item Return value: $classname
1250
27f01d1f 1251=back
77254782 1252
2053ab2a 1253Returns the class name for objects in the given relationship.
77254782 1254
1255=cut
1256
1257sub related_class {
1258 my ($self, $rel) = @_;
1259 if( !$self->has_relationship( $rel ) ) {
1260 $self->throw_exception("No such relationship '$rel'");
1261 }
1262 return $self->schema->class($self->relationship_info($rel)->{source});
1263}
1264
5ac6a044 1265=head2 resultset
1266
391ccf38 1267=over 4
1268
1269=item Arguments: None
1270
1271=item Return value: $resultset
1272
1273=back
1274
bcc5a210 1275Returns a resultset for the given source. This will initially be created
1276on demand by calling
5ac6a044 1277
988bf309 1278 $self->resultset_class->new($self, $self->resultset_attributes)
5ac6a044 1279
bcc5a210 1280but is cached from then on unless resultset_class changes.
1281
5ac6a044 1282=head2 resultset_class
1283
391ccf38 1284=over 4
1285
1286=item Arguments: $classname
1287
1288=item Return value: $classname
1289
1290=back
1291
1292 package My::ResultSetClass;
d7be2784 1293 use base 'DBIx::Class::ResultSet';
1294 ...
1295
1296 $source->resultset_class('My::ResultSet::Class');
1297
988bf309 1298Set the class of the resultset, this is useful if you want to create your
1299own resultset methods. Create your own class derived from
e4773415 1300L<DBIx::Class::ResultSet>, and set it here. If called with no arguments,
1301this method returns the name of the existing resultset class, if one
1302exists.
5ac6a044 1303
1304=head2 resultset_attributes
1305
391ccf38 1306=over 4
1307
1308=item Arguments: \%attrs
1309
1310=item Return value: \%attrs
1311
1312=back
1313
d7be2784 1314 $source->resultset_attributes({ order_by => [ 'id' ] });
1315
391ccf38 1316Store a collection of resultset attributes, that will be set on every
1317L<DBIx::Class::ResultSet> produced from this result source. For a full
1318list see L<DBIx::Class::ResultSet/ATTRIBUTES>.
5ac6a044 1319
1320=cut
1321
1322sub resultset {
1323 my $self = shift;
27f01d1f 1324 $self->throw_exception(
1325 'resultset does not take any arguments. If you want another resultset, '.
1326 'call it on the schema instead.'
1327 ) if scalar @_;
428c2b82 1328
428c2b82 1329 return $self->resultset_class->new(
e6c747fd 1330 $self,
1331 {
1332 %{$self->{resultset_attributes}},
1333 %{$self->schema->default_resultset_attributes}
1334 },
27f01d1f 1335 );
5ac6a044 1336}
1337
bab77431 1338=head2 source_name
1339
1340=over 4
1341
1342=item Arguments: $source_name
1343
391ccf38 1344=item Result value: $source_name
1345
bab77431 1346=back
1347
391ccf38 1348Set an alternate name for the result source when it is loaded into a schema.
1349This is useful if you want to refer to a result source by a name other than
bab77431 1350its class name.
1351
1352 package ArchivedBooks;
1353 use base qw/DBIx::Class/;
1354 __PACKAGE__->table('books_archive');
1355 __PACKAGE__->source_name('Books');
1356
1357 # from your schema...
1358 $schema->resultset('Books')->find(1);
1359
aec3eff1 1360=head2 handle
1361
1362Obtain a new handle to this source. Returns an instance of a
1363L<DBIx::Class::ResultSourceHandle>.
1364
1365=cut
1366
1367sub handle {
1368 return new DBIx::Class::ResultSourceHandle({
1369 schema => $_[0]->schema,
3441fd57 1370 source_moniker => $_[0]->source_name
aec3eff1 1371 });
1372}
1373
701da8c4 1374=head2 throw_exception
1375
2053ab2a 1376See L<DBIx::Class::Schema/"throw_exception">.
701da8c4 1377
1378=cut
1379
1380sub throw_exception {
1381 my $self = shift;
75d07914 1382 if (defined $self->schema) {
701da8c4 1383 $self->schema->throw_exception(@_);
1384 } else {
1385 croak(@_);
1386 }
1387}
1388
d2f3e87b 1389=head2 sqlt_deploy_hook($sqlt_table)
1390
391ccf38 1391=over 4
1392
1393=item Arguments: $source, $sqlt_table
1394
1395=item Return value: undefined
1396
1397=back
1398
1399An optional sub which you can declare in your own Result class that will get
d2f3e87b 1400passed the L<SQL::Translator::Schema::Table> object when you deploy the schema
1401via L</create_ddl_dir> or L</deploy>.
1402
391ccf38 1403This is useful to make L<SQL::Translator> create non-unique indexes,
1404or set table options such as C<Engine=INNOFB>.
1405
d2f3e87b 1406For an example of what you can do with this, see
1407L<DBIx::Class::Manual::Cookbook/Adding Indexes And Functions To Your SQL>.
1408
9c992ba1 1409=head1 AUTHORS
1410
1411Matt S. Trout <mst@shadowcatsystems.co.uk>
1412
1413=head1 LICENSE
1414
1415You may distribute this code under the same terms as Perl itself.
1416
1417=cut
1418
b25e9fa0 14191;