From d70e0236df61d69c9299fe63df94da35c87ee2d8 Mon Sep 17 00:00:00 2001 From: Marcelo Silveira Date: Thu, 9 Feb 2012 01:20:52 -0200 Subject: Added where option to add_index to support postgresql partial indices The `add_index` method now supports a `where` option that receives a string with the partial index criteria. add_index(:accounts, :code, :where => "active") Generates CREATE INDEX index_accounts_on_code ON accounts(code) WHERE active --- .../test/cases/adapters/postgresql/active_schema_test.rb | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'activerecord/test') diff --git a/activerecord/test/cases/adapters/postgresql/active_schema_test.rb b/activerecord/test/cases/adapters/postgresql/active_schema_test.rb index e4746d4aa3..447d729e52 100644 --- a/activerecord/test/cases/adapters/postgresql/active_schema_test.rb +++ b/activerecord/test/cases/adapters/postgresql/active_schema_test.rb @@ -21,6 +21,18 @@ class PostgresqlActiveSchemaTest < ActiveRecord::TestCase assert_equal %(CREATE DATABASE "aimonetti" ENCODING = 'latin1'), create_database(:aimonetti, :encoding => :latin1) end + def test_add_index + # add_index calls index_name_exists? which can't work since execute is stubbed + ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.send(:define_method, :index_name_exists?) do |*| + false + end + + expected = %(CREATE UNIQUE INDEX "index_people_on_last_name" ON "people" ("last_name") WHERE state = 'active') + assert_equal expected, add_index(:people, :last_name, :unique => true, :where => "state = 'active'") + + ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.send(:remove_method, :index_name_exists?) + end + private def method_missing(method_symbol, *arguments) ActiveRecord::Base.connection.send(method_symbol, *arguments) -- cgit v1.2.3 From 7ef22fce7cdb955aba3b2f45629a711592336b1f Mon Sep 17 00:00:00 2001 From: Marcelo Silveira Date: Thu, 9 Feb 2012 03:28:11 -0200 Subject: Made schema dumper recognize partial indices' where statements --- .../test/cases/adapters/postgresql/postgresql_adapter_test.rb | 6 ++++++ activerecord/test/cases/migration/index_test.rb | 6 ++++++ activerecord/test/cases/schema_dumper_test.rb | 9 +++++++++ activerecord/test/schema/schema.rb | 1 + 4 files changed, 22 insertions(+) (limited to 'activerecord/test') diff --git a/activerecord/test/cases/adapters/postgresql/postgresql_adapter_test.rb b/activerecord/test/cases/adapters/postgresql/postgresql_adapter_test.rb index d57794daf8..898d28456b 100644 --- a/activerecord/test/cases/adapters/postgresql/postgresql_adapter_test.rb +++ b/activerecord/test/cases/adapters/postgresql/postgresql_adapter_test.rb @@ -179,6 +179,12 @@ module ActiveRecord assert_equal Arel.sql('$2'), bind end + def test_partial_index + @connection.add_index 'ex', %w{ id number }, :name => 'partial', :where => "number > 100" + index = @connection.indexes('ex').find { |idx| idx.name == 'partial' } + assert_equal "(number > 100)", index.where + end + private def insert(ctx, data) binds = data.map { |name, value| diff --git a/activerecord/test/cases/migration/index_test.rb b/activerecord/test/cases/migration/index_test.rb index 89cf0f5e93..c5a479fcdb 100644 --- a/activerecord/test/cases/migration/index_test.rb +++ b/activerecord/test/cases/migration/index_test.rb @@ -169,6 +169,12 @@ module ActiveRecord connection.add_index("testings", ["last_name", "first_name"], :order => :desc) connection.remove_index("testings", ["last_name", "first_name"]) end + + # Selected adapters support partial indices + if current_adapter?(:PostgreSQLAdapter) + connection.add_index("testings", ["last_name"], :where => "first_name = 'john doe'") + connection.remove_index("testings", ["last_name"]) + end end end diff --git a/activerecord/test/cases/schema_dumper_test.rb b/activerecord/test/cases/schema_dumper_test.rb index abeb56fd3f..c79382a984 100644 --- a/activerecord/test/cases/schema_dumper_test.rb +++ b/activerecord/test/cases/schema_dumper_test.rb @@ -185,6 +185,15 @@ class SchemaDumperTest < ActiveRecord::TestCase assert_equal 'add_index "companies", ["firm_id", "type", "rating", "ruby_type"], :name => "company_index"', index_definition end + def test_schema_dumps_partial_indices + index_definition = standard_dump.split(/\n/).grep(/add_index.*company_partial_index/).first.strip + if current_adapter?(:PostgreSQLAdapter) + assert_equal 'add_index "companies", ["firm_id", "type"], :name => "company_partial_index", :where => "(rating > 10)"', index_definition + else + assert_equal 'add_index "companies", ["firm_id", "type"], :name => "company_partial_index"', index_definition + end + end + def test_schema_dump_should_honor_nonstandard_primary_keys output = standard_dump match = output.match(%r{create_table "movies"(.*)do}) diff --git a/activerecord/test/schema/schema.rb b/activerecord/test/schema/schema.rb index da0c4cecdd..d473680fdc 100644 --- a/activerecord/test/schema/schema.rb +++ b/activerecord/test/schema/schema.rb @@ -175,6 +175,7 @@ ActiveRecord::Schema.define do end add_index :companies, [:firm_id, :type, :rating, :ruby_type], :name => "company_index" + add_index :companies, [:firm_id, :type], :name => "company_partial_index", :where => "rating > 10" create_table :computers, :force => true do |t| t.integer :developer, :null => false -- cgit v1.2.3 From aaffc2acd5fa3104fa936c334ef9d50774071c8b Mon Sep 17 00:00:00 2001 From: Marcelo Silveira Date: Thu, 9 Feb 2012 19:04:07 -0200 Subject: improved test case for partial indices --- activerecord/test/cases/migration/index_test.rb | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'activerecord/test') diff --git a/activerecord/test/cases/migration/index_test.rb b/activerecord/test/cases/migration/index_test.rb index c5a479fcdb..dd9492924c 100644 --- a/activerecord/test/cases/migration/index_test.rb +++ b/activerecord/test/cases/migration/index_test.rb @@ -169,14 +169,17 @@ module ActiveRecord connection.add_index("testings", ["last_name", "first_name"], :order => :desc) connection.remove_index("testings", ["last_name", "first_name"]) end - - # Selected adapters support partial indices - if current_adapter?(:PostgreSQLAdapter) - connection.add_index("testings", ["last_name"], :where => "first_name = 'john doe'") - connection.remove_index("testings", ["last_name"]) - end end + def test_add_partial_index + skip 'only on pg' unless current_adapter?(:PostgreSQLAdapter) + + connection.add_index("testings", "last_name", :where => "first_name = 'john doe'") + assert connection.index_exists?("testings", "last_name") + + connection.remove_index("testings", "last_name") + assert !connection.index_exists?("testings", "last_name") + end end end end -- cgit v1.2.3