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