merge resultset branch through revision 378
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / PK.pm
CommitLineData
dbd7896f 1package DBIx::Class::PK;
2
3use strict;
4use warnings;
6eec7501 5use Tie::IxHash;
dbd7896f 6
1edd1722 7use base qw/DBIx::Class::Row/;
dbd7896f 8
9__PACKAGE__->mk_classdata('_primaries' => {});
10
34d52be2 11=head1 NAME
12
13DBIx::Class::PK - Primary Key class
14
15=head1 SYNOPSIS
16
17=head1 DESCRIPTION
18
8091aa91 19This class contains methods for handling primary keys and methods
20depending on them.
34d52be2 21
22=head1 METHODS
23
34d52be2 24=cut
25
dbd7896f 26sub _ident_cond {
27 my ($class) = @_;
28 return join(" AND ", map { "$_ = ?" } keys %{$class->_primaries});
29}
30
31sub _ident_values {
32 my ($self) = @_;
33 return (map { $self->{_column_data}{$_} } keys %{$self->_primaries});
34}
35
8091aa91 36=head2 set_primary_key(@cols)
076652e8 37
8091aa91 38Defines one or more columns as primary key for this class. Should be
39called after C<columns>.
076652e8 40
41=cut
42
510ca912 43sub set_primary_key {
dbd7896f 44 my ($class, @cols) = @_;
6a94f7f4 45 # check if primary key columns are valid columns
46 for (@cols) {
47 $class->throw( "Column $_ can't be used as primary key because it isn't defined in $class" )
48 unless $class->has_column($_);
49 }
dbd7896f 50 my %pri;
48700d09 51 tie %pri, 'Tie::IxHash', map { $_ => {} } @cols;
dbd7896f 52 $class->_primaries(\%pri);
53}
54
8091aa91 55=head2 find(@colvalues), find(\%cols)
076652e8 56
8091aa91 57Finds a row based on its primary key(s).
076652e8 58
59=cut
60
656796f2 61sub find {
dbd7896f 62 my ($class, @vals) = @_;
c687b87e 63 my $attrs = (@vals > 1 && ref $vals[$#vals] eq 'HASH' ? pop(@vals) : {});
dbd7896f 64 my @pk = keys %{$class->_primaries};
656796f2 65 $class->throw( "Can't find unless primary columns are defined" )
78bab9ca 66 unless @pk;
dbd7896f 67 my $query;
68 if (ref $vals[0] eq 'HASH') {
69 $query = $vals[0];
a3018bd3 70 } elsif (@pk == @vals) {
1a14aa3f 71 $query = {};
72 @{$query}{@pk} = @vals;
73 #my $ret = ($class->search_literal($class->_ident_cond, @vals, $attrs))[0];
12bbb339 74 #warn "$class: ".join(', ', %{$ret->{_column_data}});
1a14aa3f 75 #return $ret;
dbd7896f 76 } else {
77 $query = {@vals};
78 }
656796f2 79 $class->throw( "Can't find unless all primary keys are specified" )
dbd7896f 80 unless (keys %$query >= @pk); # If we check 'em we run afoul of uc/lc
81 # column names etc. Not sure what to do yet
1a14aa3f 82 #return $class->search($query)->next;
83 my @cols = $class->_select_columns;
84 my @row = $class->storage->select_single($class->_table_name, \@cols, $query);
85 return (@row ? $class->_row_to_object(\@cols, \@row) : ());
dbd7896f 86}
87
8091aa91 88=head2 discard_changes
076652e8 89
8091aa91 90Re-selects the row from the database, losing any changes that had
91been made.
076652e8 92
93=cut
94
510ca912 95sub discard_changes {
96 my ($self) = @_;
97 delete $self->{_dirty_columns};
8d5134b0 98 return unless $self->in_storage; # Don't reload if we aren't real!
656796f2 99 my ($reload) = $self->find($self->id);
c1d23573 100 unless ($reload) { # If we got deleted in the mean-time
8d5134b0 101 $self->in_storage(0);
c1d23573 102 return $self;
103 }
4a07648a 104 delete @{$self}{keys %$self};
105 @{$self}{keys %$reload} = values %$reload;
c1d23573 106 return $self;
510ca912 107}
108
8091aa91 109=head2 id
076652e8 110
8091aa91 111Returns the primary key(s) for a row. Can't be called as
076652e8 112a class method.
113
114=cut
115
604d9f38 116sub id {
117 my ($self) = @_;
78bab9ca 118 $self->throw( "Can't call id() as a class method" ) unless ref $self;
604d9f38 119 my @pk = $self->_ident_values;
120 return (wantarray ? @pk : $pk[0]);
121}
122
8091aa91 123=head2 primary_columns
076652e8 124
8091aa91 125Read-only accessor which returns the list of primary keys for a class
126(in scalar context, only returns the first primary key).
076652e8 127
128=cut
129
8b445e33 130sub primary_columns {
131 return keys %{shift->_primaries};
132}
133
8091aa91 134=head2 ID
135
136Returns a unique id string identifying a row object by primary key.
137Used by L<DBIx::Class::CDBICompat::LiveObjectIndex> and
138L<DBIx::Class::ObjectCache>.
139
140=cut
141
48700d09 142sub ID {
143 my ($self) = @_;
144 $self->throw( "Can't call ID() as a class method" ) unless ref $self;
145 return undef unless $self->in_storage;
146 return $self->_create_ID(map { $_ => $self->{_column_data}{$_} } keys %{$self->_primaries});
147}
148
149sub _create_ID {
150 my ($class,%vals) = @_;
90f3f5ff 151 return undef unless 0 == grep { !defined } values %vals;
48700d09 152 $class = ref $class || $class;
153 return join '|', $class, map { $_ . '=' . $vals{$_} } sort keys %vals;
154}
155
103647d5 156sub ident_condition {
157 my ($self) = @_;
158 my %cond;
159 $cond{$_} = $self->get_column($_) for $self->primary_columns;
160 return \%cond;
161}
162
dbd7896f 1631;
34d52be2 164
34d52be2 165=head1 AUTHORS
166
daec44b8 167Matt S. Trout <mst@shadowcatsystems.co.uk>
34d52be2 168
169=head1 LICENSE
170
171You may distribute this code under the same terms as Perl itself.
172
173=cut
174