Revision history for DBIx::Class
0.07001
+ - restore automatic aliasing in ResultSet::find() on nonunique queries
+ - allow aliases in ResultSet::find() queries (in cases of relationships
+ with prefetch)
- pass $attrs to find from update_or_create so a specific key can be
provided
- remove anonymous blesses to avoid major speed hit on Fedora Core 5's
my @unique_queries = $self->_unique_queries($input_query, $attrs);
- # Handle cases where the ResultSet defines the query, or where the user is
- # abusing find
- my $query = @unique_queries ? \@unique_queries : $input_query;
+ # Build the final query: Default to the disjunction of the unique queries,
+ # but allow the input query in case the ResultSet defines the query or the
+ # user is abusing find
+ my $alias = exists $attrs->{alias} ? $attrs->{alias} : $self->{attrs}{alias};
+ my $query = @unique_queries
+ ? [ map { $self->_add_alias($_, $alias) } @unique_queries ]
+ : $self->_add_alias($input_query, $alias);
# Run the query
if (keys %$attrs) {
}
}
+# _add_alias
+#
+# Add the specified alias to the specified query hash. A copy is made so the
+# original query is not modified.
+
+sub _add_alias {
+ my ($self, $query, $alias) = @_;
+
+ my %aliased = %$query;
+ foreach my $col (grep { ! m/\./ } keys %aliased) {
+ $aliased{"$alias.$col"} = delete $aliased{$col};
+ }
+
+ return \%aliased;
+}
+
# _unique_queries
#
# Build a list of queries which satisfy unique constraints.
sub _unique_queries {
my ($self, $query, $attrs) = @_;
- my $alias = $self->{attrs}{alias};
my @constraint_names = exists $attrs->{key}
? ($attrs->{key})
: $self->result_source->unique_constraint_names;
my $num_query = scalar keys %$unique_query;
next unless $num_query;
- # Add the ResultSet's alias
- foreach my $col (grep { ! m/\./ } keys %$unique_query) {
- $unique_query->{"$alias.$col"} = delete $unique_query->{$col};
- }
-
# XXX: Assuming quite a bit about $self->{attrs}{where}
my $num_cols = scalar @unique_cols;
my $num_where = exists $self->{attrs}{where}
$self->throw_exception(
"Can't abstract implicit construct, condition not a hash"
) if ($self->{cond} && !(ref $self->{cond} eq 'HASH'));
- my %new = %$values;
+
my $alias = $self->{attrs}{alias};
- foreach my $key (keys %{$self->{cond}||{}}) {
- $new{$1} = $self->{cond}{$key} if ($key =~ m/^(?:\Q${alias}.\E)?([^.]+)$/);
- }
+ my %new = (
+ %{ $self->_remove_alias($values, $alias) },
+ %{ $self->_remove_alias($self->{cond}, $alias) },
+ );
+
my $obj = $self->result_class->new(\%new);
$obj->result_source($self->result_source) if $obj->can('result_source');
return $obj;
}
+# _remove_alias
+#
+# Remove the specified alias from the specified query hash. A copy is made so
+# the original query is not modified.
+
+sub _remove_alias {
+ my ($self, $query, $alias) = @_;
+
+ my %unaliased = %{ $query || {} };
+ foreach my $key (keys %unaliased) {
+ $unaliased{$1} = delete $unaliased{$key}
+ if $key =~ m/^(?:\Q$alias\E\.)?([^.]+)$/;
+ }
+
+ return \%unaliased;
+}
+
=head2 find_or_new
=over 4
delete $type_info->{artistid}{size};
delete $type_info->{name}{size};
+delete $type_info->{agent}{size};
my $test_type_info = {
'artistid' => {
'data_type' => 'varchar',
'is_nullable' => 0,
},
+ 'agent' => {
+ 'data_type' => 'integer',
+ 'is_nullable' => 0,
+ },
};
is_deeply($type_info, $test_type_info, 'columns_info_for - column data types');
--- /dev/null
+use strict;
+use warnings;
+
+use Test::More;
+use lib qw(t/lib);
+use DBICTest;
+
+my $schema = DBICTest->init_schema();
+
+plan tests => 8;
+
+my $label = $schema->resultset('Label')->find({ labelid => 1 });
+
+# Check that you can leave off the alias
+{
+ my $existing_agent = $label->agents->find_or_create({
+ name => 'Ted',
+ });
+ ok(! $existing_agent->is_changed, 'find_or_create on prefetched has_many with same column names: row is clean');
+ is($existing_agent->name, 'Ted', 'find_or_create on prefetched has_many with same column names: name matches existing entry');
+
+ my $new_agent = $label->agents->find_or_create({
+ name => 'Someone Else',
+ });
+ ok(! $new_agent->is_changed, 'find_or_create on prefetched has_many with same column names: row is clean');
+ is($new_agent->name, 'Someone Else', 'find_or_create on prefetched has_many with same column names: name matches');
+}
+
+# Check that you can specify the alias
+{
+ my $existing_agent = $label->agents->find_or_create({
+ 'me.name' => 'Someone Else',
+ });
+ ok(! $existing_agent->is_changed, 'find_or_create on prefetched has_many with same column names: row is clean');
+ is($existing_agent->name, 'Someone Else', 'find_or_create on prefetched has_many with same column names: can be disambiguated with "me." for existing entry');
+
+ my $new_agent = $label->agents->find_or_create({
+ 'me.name' => 'Some New Guy',
+ });
+ ok(! $new_agent->is_changed, 'find_or_create on prefetched has_many with same column names: row is clean');
+ is($new_agent->name, 'Some New Guy', 'find_or_create on prefetched has_many with same column names: can be disambiguated with "me." for new entry');
+}
my $self = shift;
my $schema = shift;
+ $schema->populate('Label', [
+ [ qw/labelid name/ ],
+ [ 1, 'Acme Records' ],
+ ]);
+
+ $schema->populate('Agent', [
+ [ qw/agentid label name/ ],
+ [ 1, 1, 'Ted' ],
+ ]);
+
$schema->populate('Artist', [
- [ qw/artistid name/ ],
- [ 1, 'Caterwauler McCrae' ],
- [ 2, 'Random Boy Band' ],
- [ 3, 'We Are Goth' ],
+ [ qw/artistid agent name/ ],
+ [ 1, 1, 'Caterwauler McCrae' ],
+ [ 2, 1, 'Random Boy Band' ],
+ [ 3, 1, 'We Are Goth' ],
]);
$schema->populate('CD', [
no warnings qw/qw/;
__PACKAGE__->load_classes(qw/
+ Agent
Artist
Employee
CD
+ Label
Link
Bookmark
#dummy
--- /dev/null
+package # hide from PAUSE
+ DBICTest::Schema::Agent;
+
+use base 'DBIx::Class::Core';
+
+__PACKAGE__->table('agent');
+__PACKAGE__->add_columns(
+ 'agentid' => {
+ data_type => 'integer',
+ is_auto_increment => 1
+ },
+ 'label' => {
+ data_type => 'integer',
+ },
+ 'name' => {
+ data_type => 'varchar',
+ size => 100,
+ is_nullable => 1,
+ },
+);
+__PACKAGE__->set_primary_key('agentid');
+
+__PACKAGE__->has_many( artists => 'DBICTest::Schema::Artist' );
+__PACKAGE__->belongs_to( label => 'DBICTest::Schema::Label' );
+
+1;
data_type => 'integer',
is_auto_increment => 1
},
+ 'agent' => {
+ data_type => 'integer',
+ is_nullable => 1,
+ },
'name' => {
data_type => 'varchar',
size => 100,
__PACKAGE__->mk_classdata('field_name_for', {
artistid => 'primary key',
+ agent => 'agent',
name => 'artist name',
});
{ order_by => 'year' },
);
+__PACKAGE__->belongs_to( agent => 'DBICTest::Schema::Agent' );
+
__PACKAGE__->has_many( twokeys => 'DBICTest::Schema::TwoKeys' );
__PACKAGE__->has_many( onekeys => 'DBICTest::Schema::OneKey' );
--- /dev/null
+package # hide from PAUSE
+ DBICTest::Schema::Label;
+
+use base 'DBIx::Class::Core';
+
+__PACKAGE__->table('label');
+__PACKAGE__->add_columns(
+ 'labelid' => {
+ data_type => 'integer',
+ is_auto_increment => 1
+ },
+ 'name' => {
+ data_type => 'varchar',
+ size => 100,
+ is_nullable => 1,
+ },
+);
+__PACKAGE__->set_primary_key('labelid');
+
+__PACKAGE__->has_many(
+ agents => 'DBICTest::Schema::Agent',
+ undef,
+ { prefetch => 'artists' }
+);
+
+1;
--
-- Created by SQL::Translator::Producer::SQLite
--- Created on Sun Jul 23 00:23:30 2006
+-- Created on Fri Aug 4 19:03:21 2006
--
BEGIN TRANSACTION;
--
CREATE TABLE artist (
artistid INTEGER PRIMARY KEY NOT NULL,
+ agent integer,
+ name varchar(100)
+);
+
+--
+-- Table: label
+--
+CREATE TABLE label (
+ labelid INTEGER PRIMARY KEY NOT NULL,
name varchar(100)
);
);
--
--- Table: link
---
-CREATE TABLE link (
- id INTEGER PRIMARY KEY NOT NULL,
- url varchar(100),
- title varchar(100)
-);
-
---
-- Table: tags
--
CREATE TABLE tags (
);
--
+-- Table: agent
+--
+CREATE TABLE agent (
+ agentid INTEGER PRIMARY KEY NOT NULL,
+ label integer NOT NULL,
+ name varchar(100)
+);
+
+--
+-- Table: link
+--
+CREATE TABLE link (
+ id INTEGER PRIMARY KEY NOT NULL,
+ url varchar(100),
+ title varchar(100)
+);
+
+--
-- Table: treelike
--
CREATE TABLE treelike (