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