Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

fix bugs re: uniqueness constraints, add specs

  • Loading branch information...
commit ce674998ec345416890ca1eaded2e652ddaa3b91 1 parent cb57a5f
@barunio barunio authored
Showing with 104 additions and 20 deletions.
  1. +32 −18 lib/polymorpheus/mysql_adapter.rb
  2. +72 −2 spec/mysql2_adapter_spec.rb
View
50 lib/polymorpheus/mysql_adapter.rb
@@ -21,15 +21,21 @@ module MysqlAdapter
# `products` table
#
# options: a hash, corrently only accepts one option that allows us to
- # add an additional uniqueness constraint. so if the columns
- # hash was specified as above, and we supplied options of
- # { :unique => 'picture_url' }
+ # add an additional uniqueness constraint.
+ # if the columns hash was specified as above, and we supplied
+ # options of
+ # { :unique => true }
# then this would create a uniqueness constraint in the database
- # that would ensure that no two employees could have the same
- # picture_url and no two products could have the same
- # picture_url
- # (it would allow and employee and a product to have the same
- # picture_url)
+ # that would ensure that any given employee_id could only be in
+ # the table once, and that any given product_id could only be in
+ # the table once.
+ #
+ # alternatively, the user can also supply a column name or array
+ # of column names to the :unique option:
+ # { :unique => 'picture_url' }
+ # This would allow an employee_id (or product_id) to appear
+ # multiple times in the table, but no two employee ids would
+ # be able to have the same picture_url.
def add_polymorphic_constraints(table, columns, options={})
column_names = columns.keys.sort
@@ -116,22 +122,30 @@ def poly_create_triggers(table, columns)
end
def poly_create_index(table, column, unique_cols)
- unique_cols = unique_cols.collect(&:to_s)
- name = poly_index_name(table, column, unique_cols)
+ if unique_cols == [true]
+ unique_cols = [column]
+ else
+ unique_cols = [column] + unique_cols
+ end
+ name = poly_index_name(table, unique_cols)
execute %{
- CREATE UNIQUE INDEX #{name} ON #{table} (#{column},#{unique_cols.join(',')})
+ CREATE UNIQUE INDEX #{name} ON #{table} (#{unique_cols.join(', ')})
}
end
def poly_remove_index(table, column, unique_cols)
- unique_cols = unique_cols.collect(&:to_s)
- name = poly_index_name(table, column, unique_cols)
+ if unique_cols == [true]
+ unique_cols = [column]
+ else
+ unique_cols = [column] + unique_cols
+ end
+ name = poly_index_name(table, unique_cols)
execute %{ DROP INDEX #{name} ON #{table} }
end
- def poly_index_name(table, column, unique_cols)
- prefix = "pfk_#{table}"
- generate_name prefix, [column] + unique_cols
+ def poly_index_name(table, columns)
+ prefix = "pfk_#{table}_"
+ generate_name prefix, columns
end
def poly_create_indexes(table, columns, unique_cols)
@@ -148,10 +162,10 @@ def poly_remove_indexes(table, columns, unique_cols)
def generate_name(prefix, columns)
# names can be at most 64 characters long
- length_per_col = (64 - prefix.length) / columns.length
+ col_length = (64 - prefix.length) / columns.length
prefix +
- columns.map { |c| c.gsub('_','').first(length_per_col - 1) }.join('_')
+ columns.map { |c| c.to_s.gsub('_','').first(col_length-1) }.join('_')
end
end
View
74 spec/mysql2_adapter_spec.rb
@@ -34,10 +34,10 @@ class << ActiveRecord::Base.connection
shared_examples_for "migration statements" do
describe "#add_polymorphic_constraints" do
- before { connection.add_polymorphic_constraints(table, columns) }
+ before { connection.add_polymorphic_constraints(table, columns, options) }
specify do
- clean_sql(sql.join("\n")).should == clean_sql(trigger_sql + fkey_sql)
+ clean_sql(sql.join("\n")).should == clean_sql(full_constraints_sql)
end
end
@@ -53,6 +53,7 @@ class << ActiveRecord::Base.connection
context "when the table and column names are not too long" do
let(:table) { 'pets' }
let(:columns) { { 'kitty_id' => 'cats.name', 'dog_id' => 'dogs.id' } }
+ let(:options) { {} }
let(:trigger_sql) do
%{
@@ -82,7 +83,67 @@ class << ActiveRecord::Base.connection
}
end
+ let(:full_constraints_sql) { trigger_sql + fkey_sql }
+
it_behaves_like "migration statements"
+
+ context "and we specify a uniqueness constraint as true" do
+ let(:options) { { :unique => true } }
+ let(:unique_key_sql) do
+ %{
+ CREATE UNIQUE INDEX pfk_pets_dogid ON pets (dog_id)
+ CREATE UNIQUE INDEX pfk_pets_kittyid ON pets (kitty_id)
+ }
+ end
+
+ let(:full_constraints_sql) { trigger_sql + unique_key_sql + fkey_sql }
+
+ it_behaves_like "migration statements"
+ end
+
+ context "and we specify a uniqueness constraint as a string" do
+ let(:options) { { :unique => 'field1' } }
+ let(:unique_key_sql) do
+ %{
+ CREATE UNIQUE INDEX pfk_pets_dogid_field1 ON pets (dog_id, field1)
+ CREATE UNIQUE INDEX pfk_pets_kittyid_field1 ON pets (kitty_id, field1)
+ }
+ end
+
+ let(:full_constraints_sql) { trigger_sql + unique_key_sql + fkey_sql }
+
+ it_behaves_like "migration statements"
+ end
+
+ context "and we specify a uniqueness constraint as an array" do
+ let(:options) { { :unique => [:foo, :bar] } }
+ let(:unique_key_sql) do
+ %{
+ CREATE UNIQUE INDEX pfk_pets_dogid_foo_bar ON pets (dog_id, foo, bar)
+ CREATE UNIQUE INDEX pfk_pets_kittyid_foo_bar ON pets (kitty_id, foo, bar)
+ }
+ end
+
+ let(:full_constraints_sql) { trigger_sql + unique_key_sql + fkey_sql }
+
+ it_behaves_like "migration statements"
+ end
+
+ context "and we specify a uniqueness constraint on fields with really long names" do
+ let(:options) do
+ { :unique => [:fee_was_a_buddhist_prodigy, :ground_control_to_major_tom] }
+ end
+ let(:unique_key_sql) do
+ %{
+ CREATE UNIQUE INDEX pfk_pets_dogid_feewasabuddhistpr_groundcontroltoma ON pets (dog_id, fee_was_a_buddhist_prodigy, ground_control_to_major_tom)
+ CREATE UNIQUE INDEX pfk_pets_kittyid_feewasabuddhistpr_groundcontroltoma ON pets (kitty_id, fee_was_a_buddhist_prodigy, ground_control_to_major_tom)
+ }
+ end
+
+ let(:full_constraints_sql) { trigger_sql + unique_key_sql + fkey_sql }
+
+ it_behaves_like "migration statements"
+ end
end
context "when the table and column names combined are very long" do
@@ -91,6 +152,7 @@ class << ActiveRecord::Base.connection
{ 'im_too_cool_to_vote_and_ill_only_ride_a_fixie' => 'hipster.id',
'really_im_not_doping_i_just_practice_a_lot' => 'professional.id' }
end
+ let(:options) { {} }
let(:trigger_sql) do
%{
@@ -120,6 +182,14 @@ class << ActiveRecord::Base.connection
}
end
+ let(:unique_key_sql) do
+ %{
+ CREATE UNIQUE INDEX pfk_blah
+ }
+ end
+
+ let(:full_constraints_sql) { trigger_sql + fkey_sql }
+
it_behaves_like "migration statements"
end
Please sign in to comment.
Something went wrong with that request. Please try again.