Add automatic naming of unique constraints
Daniel Westermann-Clark [Sun, 28 May 2006 01:30:16 +0000 (01:30 +0000)]
Changes
lib/DBIx/Class/ResultSet.pm
lib/DBIx/Class/ResultSource.pm
t/80unique.t
t/86sqlt.t
t/lib/DBICTest/Schema/CD.pm
t/lib/DBICTest/Schema/Producer.pm
t/lib/sqlite.sql

diff --git a/Changes b/Changes
index cd9962b..a5dd688 100644 (file)
--- a/Changes
+++ b/Changes
@@ -1,5 +1,6 @@
 Revision history for DBIx::Class
 
+        - add automatic naming of unique constraints
         - marked DB.pm as deprecated and noted it will be removed by 1.0
        - add ResultSetColumn
        - refactor ResultSet code to resolve attrs as late as poss
index cc0d1ef..1c23b4c 100644 (file)
@@ -262,7 +262,7 @@ a row by its primary key:
 You can also find a row by a specific unique constraint using the C<key>
 attribute. For example:
 
-  my $cd = $schema->resultset('CD')->find('Massive Attack', 'Mezzanine', { key => 'artist_title' });
+  my $cd = $schema->resultset('CD')->find('Massive Attack', 'Mezzanine', { key => 'cd_artist_title' });
 
 Additionally, you can specify the columns explicitly by name:
 
@@ -271,7 +271,7 @@ Additionally, you can specify the columns explicitly by name:
       artist => 'Massive Attack',
       title  => 'Mezzanine',
     },
-    { key => 'artist_title' }
+    { key => 'cd_artist_title' }
   );
 
 If no C<key> is specified and you explicitly name columns, it searches on all
@@ -1312,7 +1312,7 @@ constraint. For example:
       artist => 'Massive Attack',
       title  => 'Mezzanine',
     },
-    { key => 'artist_title' }
+    { key => 'cd_artist_title' }
   );
 
 See also L</find> and L</update_or_create>. For information on how to declare
@@ -1355,7 +1355,7 @@ For example:
       title  => 'Mezzanine',
       year   => 1998,
     },
-    { key => 'artist_title' }
+    { key => 'cd_artist_title' }
   );
 
 If no C<key> is specified, it searches on all unique constraints defined on the
index eb58dd5..a5da754 100644 (file)
@@ -292,13 +292,24 @@ constraint.
     constraint_name => [ qw/column1 column2/ ],
   );
 
+Alternatively, you can specify only the columns:
+
+  __PACKAGE__->add_unique_constraint([ qw/column1 column2/ ]);
+
+This will result in a unique constraint named C<table_column1_column2>, where
+C<table> is replaced with the table name.
+
 Unique constraints are used, for example, when you call
 L<DBIx::Class::ResultSet/find>. Only columns in the constraint are searched.
 
 =cut
 
 sub add_unique_constraint {
-  my ($self, $name, $cols) = @_;
+  my $self = shift;
+  my $cols = pop @_;
+  my $name = shift;
+
+  $name ||= $self->name_unique_constraint($cols);
 
   foreach my $col (@$cols) {
     $self->throw_exception("No such column $col on table " . $self->name)
@@ -310,6 +321,22 @@ sub add_unique_constraint {
   $self->_unique_constraints(\%unique_constraints);
 }
 
+=head2
+
+Return a name for a unique constraint containing the specified columns. These
+names consist of the table name and each column name, separated by underscores.
+
+For example, a constraint on a table named C<cd> containing the columns
+C<artist> and C<title> would result in a constraint name of C<cd_artist_title>.
+
+=cut
+
+sub name_unique_constraint {
+  my ($self, $cols) = @_;
+
+  return join '_', $self->name, @$cols;
+}
+
 =head2 unique_constraints
 
 Read-only accessor which returns the list of unique constraints on this source.
index 30767d2..6540333 100644 (file)
@@ -7,7 +7,10 @@ use DBICTest;
 
 my $schema = DBICTest->init_schema();
 
-plan tests => 34;
+plan tests => 36;
+
+is_deeply([ sort $schema->source('CD')->unique_constraint_names ], [ qw/cd_artist_title primary/ ], 'CD source has an automatically named unique constraint');
+is_deeply([ sort $schema->source('Producer')->unique_constraint_names ], [ qw/primary prod_name/ ], 'Producer source has a named unique constraint');
 
 my $artistid = 1;
 my $title    = 'UNIQUE Constraint';
@@ -23,14 +26,14 @@ my $cd2 = $schema->resultset('CD')->find(
     artist => $artistid,
     title  => $title,
   },
-  { key => 'artist_title' }
+  { key => 'cd_artist_title' }
 );
 
 is($cd2->get_column('artist'), $cd1->get_column('artist'), 'find by specific key: artist is correct');
 is($cd2->title, $cd1->title, 'title is correct');
 is($cd2->year, $cd1->year, 'year is correct');
 
-my $cd3 = $schema->resultset('CD')->find($artistid, $title, { key => 'artist_title' });
+my $cd3 = $schema->resultset('CD')->find($artistid, $title, { key => 'cd_artist_title' });
 
 is($cd3->get_column('artist'), $cd1->get_column('artist'), 'find by specific key, ordered columns: artist is correct');
 is($cd3->title, $cd1->title, 'title is correct');
@@ -56,7 +59,7 @@ my $cd5 = $schema->resultset('CD')->update_or_create(
     title  => $title,
     year   => 2007,
   },
-  { key => 'artist_title' }
+  { key => 'cd_artist_title' }
 );
 
 ok(! $cd5->is_changed, 'update_or_create by specific key: row is clean');
@@ -87,7 +90,7 @@ my $cd7 = $schema->resultset('CD')->find_or_create(
     title  => $title,
     year   => 2010,
   },
-  { key => 'artist_title' }
+  { key => 'cd_artist_title' }
 );
 
 is($cd7->cdid, $cd1->cdid, 'find_or_create by specific key: cdid is correct');
@@ -102,7 +105,7 @@ my $cd8 = $artist->find_or_create_related('cds',
     title  => $title,
     year   => 2020,
   },
-  { key => 'artist_title' }
+  { key => 'cd_artist_title' }
 );
 
 is($cd8->cdid, $cd1->cdid, 'find_or_create related by specific key: cdid is correct');
@@ -116,7 +119,7 @@ my $cd9 = $artist->update_or_create_related('cds',
     title  => $title,
     year   => 2021,
   },
-  { key => 'artist_title' }
+  { key => 'cd_artist_title' }
 );
 
 ok(! $cd9->is_changed, 'update_or_create by specific key: row is clean');
index d01a630..1b80e21 100644 (file)
@@ -12,7 +12,7 @@ plan skip_all => 'SQL::Translator required' if $@;
 
 my $schema = 'DBICTest::Schema';
 
-plan tests => 31;
+plan tests => 33;
 
 my $translator           =  SQL::Translator->new( 
     parser_args          => {
@@ -95,6 +95,9 @@ my @unique_constraints = (
   {'display' => 'cd artist and title unique',
    'table' => 'cd', 'cols' => ['artist', 'title'],
    'needed' => 1},
+  {'display' => 'producer name unique',
+   'table' => 'producer', 'cols' => ['name'],
+   'needed' => 1},
   {'display' => 'twokeytreelike name unique',
    'table' => 'twokeytreelike', 'cols'  => ['name'],
    'needed' => 1},
index 262d23f..7ba727c 100644 (file)
@@ -22,7 +22,7 @@ __PACKAGE__->add_columns(
   },
 );
 __PACKAGE__->set_primary_key('cdid');
-__PACKAGE__->add_unique_constraint(artist_title => [ qw/artist title/ ]);
+__PACKAGE__->add_unique_constraint([ qw/artist title/ ]);
 
 __PACKAGE__->belongs_to( artist => 'DBICTest::Schema::Artist' );
 
index 36b63a1..036f9f2 100644 (file)
@@ -15,5 +15,6 @@ __PACKAGE__->add_columns(
   },
 );
 __PACKAGE__->set_primary_key('producerid');
+__PACKAGE__->add_unique_constraint(prod_name => [ qw/name/ ]);
 
 1;
index b067ee9..d7fa393 100644 (file)
@@ -1,6 +1,6 @@
 -- 
 -- Created by SQL::Translator::Producer::SQLite
--- Created on Tue May 23 21:10:54 2006
+-- Created on Sat May 27 21:28:05 2006
 -- 
 BEGIN TRANSACTION;
 
@@ -186,5 +186,6 @@ CREATE TABLE producer (
 );
 
 CREATE UNIQUE INDEX tktlnameunique_twokeytreelike on twokeytreelike (name);
-CREATE UNIQUE INDEX artist_title_cd on cd (artist, title);
+CREATE UNIQUE INDEX cd_artist_title_cd on cd (artist, title);
+CREATE UNIQUE INDEX prod_name_producer on producer (name);
 COMMIT;