From d568fb61373074e015083ad39e0dc8168e81733b Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Wed, 9 Aug 2006 03:25:39 +0000 Subject: PostgreSQL: autodetected sequences work correctly with multiple schemas. Rely on the schema search_path instead of explicitly qualifying the sequence name with its schema. Closes #5280. git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@4737 5ecf4fe2-1ee6-0310-87b1-e25e094e27de --- activerecord/CHANGELOG | 5 +- .../connection_adapters/postgresql_adapter.rb | 5 +- .../test/schema_authorization_test_postgresql.rb | 75 ++++++++++++++++++++++ 3 files changed, 80 insertions(+), 5 deletions(-) create mode 100644 activerecord/test/schema_authorization_test_postgresql.rb diff --git a/activerecord/CHANGELOG b/activerecord/CHANGELOG index c9ffa888cb..37b367f4f1 100644 --- a/activerecord/CHANGELOG +++ b/activerecord/CHANGELOG @@ -1,16 +1,15 @@ *SVN* -<<<<<<< .mine +* PostgreSQL: autodetected sequences work correctly with multiple schemas. Rely on the schema search_path instead of explicitly qualifying the sequence name with its schema. #5280 [guy.naor@famundo.com] + * Replace Reloadable with Reloadable::Deprecated. [Nicholas Seckar] -======= * Cache nil results for has_one associations so multiple calls don't call the database. Closes #5757. [Michael A. Schoen] * Add documentation for how to disable timestamps on a per model basis. Closes #5684. [matt@mattmargolis.net Marcel Molina Jr.] * Don't save has_one associations unnecessarily. #5735 [Jonathan Viney] ->>>>>>> .r4727 * Refactor ActiveRecord::Base.reset_subclasses to #reset, and add global observer resetting. [Rick Olson] * Formally deprecate the deprecated finders. [Koz] diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb index 94584a5ea4..d2a65fec3f 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb @@ -315,8 +315,9 @@ module ActiveRecord AND def.adsrc ~* 'nextval' end_sql end - # check for existence of . in sequence name as in public.foo_sequence. if it does not exist, join the current namespace - result.last['.'] ? [result.first, result.last] : [result.first, "#{result[1]}.#{result[2]}"] + # check for existence of . in sequence name as in public.foo_sequence. if it does not exist, return unqualified sequence + # We cannot qualify unqualified sequences, as rails doesn't qualify any table access, using the search path + [result.first, result.last] rescue nil end diff --git a/activerecord/test/schema_authorization_test_postgresql.rb b/activerecord/test/schema_authorization_test_postgresql.rb new file mode 100644 index 0000000000..f13287658c --- /dev/null +++ b/activerecord/test/schema_authorization_test_postgresql.rb @@ -0,0 +1,75 @@ +require 'abstract_unit' + +class SchemaThing < ActiveRecord::Base +end + +class SchemaAuthorizationTest < Test::Unit::TestCase + self.use_transactional_fixtures = false + + TABLE_NAME = 'schema_things' + COLUMNS = [ + 'id serial primary key', + 'name character varying(50)' + ] + USERS = ['rails_pg_schema_user1', 'rails_pg_schema_user2'] + + def setup + @connection = ActiveRecord::Base.connection + @connection.execute "SET search_path TO '$user',public" + set_session_auth + USERS.each do |u| + @connection.execute "CREATE ROLE #{u}" + @connection.execute "CREATE SCHEMA AUTHORIZATION #{u}" + set_session_auth u + @connection.execute "CREATE TABLE #{TABLE_NAME} (#{COLUMNS.join(',')})" + @connection.execute "INSERT INTO #{TABLE_NAME} (name) VALUES ('#{u}')" + set_session_auth + end + end + + def teardown + set_session_auth + @connection.execute "RESET search_path" + USERS.each do |u| + @connection.execute "DROP SCHEMA #{u} CASCADE" + @connection.execute "DROP ROLE #{u}" + end + end + + def test_schema_invisible + assert_raise(ActiveRecord::StatementInvalid) do + set_session_auth + @connection.execute "SELECT * FROM #{TABLE_NAME}" + end + end + + def test_schema_uniqueness + assert_nothing_raised do + set_session_auth + USERS.each do |u| + set_session_auth u + assert_equal u, @connection.select_value("SELECT name FROM #{TABLE_NAME} WHERE id = 1") + set_session_auth + end + end + end + + def test_sequence_schema_caching + assert_nothing_raised do + USERS.each do |u| + set_session_auth u + st = SchemaThing.new :name => 'TEST1' + st.save! + st = SchemaThing.new :id => 5, :name => 'TEST2' + st.save! + set_session_auth + end + end + end + + private + def set_session_auth auth = nil + @connection.execute "SET SESSION AUTHORIZATION #{auth || 'default'}" + end + +end -- cgit v1.2.3