aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArturo Pie <arturotd08@yahoo.ca>2012-10-13 23:48:37 -0400
committerArturo Pie <arturotd08@yahoo.ca>2012-10-14 01:07:29 -0400
commit3980465f2651ae2520828d9aec3b310da69521fe (patch)
treeaa40df0021d860c21ebbc8ba97587ad5bed8fb1a
parent84c37741e005b3ac6807be1caf5255c041f12693 (diff)
downloadrails-3980465f2651ae2520828d9aec3b310da69521fe.tar.gz
rails-3980465f2651ae2520828d9aec3b310da69521fe.tar.bz2
rails-3980465f2651ae2520828d9aec3b310da69521fe.zip
#7914 get default value when type uses schema name
PostgreSQL adapter properly parses default values when using multiple schemas and domains. When using domains across schemas, PostgresSQL prefixes the type of the default value with the name of the schema where that type (or domain) is. For example, this query: ``` SELECT a.attname, d.adsrc FROM pg_attribute a LEFT JOIN pg_attrdef d ON a.attrelid = d.adrelid AND a.attnum = d.adnum WHERE a.attrelid = "defaults"'::regclass AND a.attnum > 0 AND NOT a.attisdropped ORDER BY a.attnum; ``` could return something like "'<default_value>'::pg_catalog.text" or "(''<default_value>'::pg_catalog.text)::text" for the text columns with defaults. I modified the regexp used to parse this value so that it ignores anything between ':: and \b(?:character varying|bpchar|text), and it allows to have optional parens like in the above second example.
-rw-r--r--activerecord/CHANGELOG.md5
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb2
-rw-r--r--activerecord/test/cases/defaults_test.rb40
-rw-r--r--activerecord/test/schema/postgresql_specific_schema.rb9
4 files changed, 54 insertions, 2 deletions
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md
index ef2b112b34..402c296aee 100644
--- a/activerecord/CHANGELOG.md
+++ b/activerecord/CHANGELOG.md
@@ -1,5 +1,10 @@
## Rails 3.2.9 (unreleased)
+* PostgreSQL adapter correctly fetches default values when using
+ multiple schemas and domains in a db. Fixes #7914
+
+ *Arturo Pie*
+
* Fix deprecation notice when loading a collection association that
selects columns from other tables, if a new record was previously
built using that association.
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
index ca9a29a5cb..e34acd8dae 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
@@ -145,7 +145,7 @@ module ActiveRecord
when /\A\(?(-?\d+(\.\d*)?\)?)\z/
$1
# Character types
- when /\A'(.*)'::(?:character varying|bpchar|text)\z/m
+ when /\A\(?'(.*)'::.*\b(?:character varying|bpchar|text)\z/m
$1
# Character types (8.1 formatting)
when /\AE'(.*)'::(?:character varying|bpchar|text)\z/m
diff --git a/activerecord/test/cases/defaults_test.rb b/activerecord/test/cases/defaults_test.rb
index b3a281d960..c63553ed51 100644
--- a/activerecord/test/cases/defaults_test.rb
+++ b/activerecord/test/cases/defaults_test.rb
@@ -110,3 +110,43 @@ if current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter)
end
end
end
+
+if current_adapter?(:PostgreSQLAdapter)
+ class DefaultsUsingMultipleSchemasAndDomainTest < ActiveSupport::TestCase
+ def setup
+ @connection = ActiveRecord::Base.connection
+
+ @old_search_path = @connection.schema_search_path
+ @connection.schema_search_path = "schema_1, pg_catalog"
+ @connection.create_table "defaults" do |t|
+ t.text "text_col", :default => "some value"
+ t.string "string_col", :default => "some value"
+ end
+ Default.reset_column_information
+ end
+
+ def test_text_defaults_in_new_schema_when_overriding_domain
+ assert_equal "some value", Default.new.text_col, "Default of text column was not correctly parse"
+ end
+
+ def test_string_defaults_in_new_schema_when_overriding_domain
+ assert_equal "some value", Default.new.string_col, "Default of string column was not correctly parse"
+ end
+
+ def test_bpchar_defaults_in_new_schema_when_overriding_domain
+ @connection.execute "ALTER TABLE defaults ADD bpchar_col bpchar DEFAULT 'some value'"
+ Default.reset_column_information
+ assert_equal "some value", Default.new.bpchar_col, "Default of bpchar column was not correctly parse"
+ end
+
+ def test_text_defaults_after_updating_column_default
+ @connection.execute "ALTER TABLE defaults ALTER COLUMN text_col SET DEFAULT 'some text'::schema_1.text"
+ assert_equal "some text", Default.new.text_col, "Default of text column was not correctly parse after updating default using '::text' since postgreSQL will add parens to the default in db"
+ end
+
+ def teardown
+ @connection.schema_search_path = @old_search_path
+ Default.reset_column_information
+ end
+ end
+end
diff --git a/activerecord/test/schema/postgresql_specific_schema.rb b/activerecord/test/schema/postgresql_specific_schema.rb
index 5cf9a207f3..34e24b5a2e 100644
--- a/activerecord/test/schema/postgresql_specific_schema.rb
+++ b/activerecord/test/schema/postgresql_specific_schema.rb
@@ -10,6 +10,8 @@ ActiveRecord::Schema.define do
execute "ALTER TABLE companies ALTER COLUMN id SET DEFAULT nextval('companies_nonstd_seq')"
execute 'DROP SEQUENCE IF EXISTS companies_id_seq'
+ execute "DROP SCHEMA IF EXISTS schema_1 CASCADE"
+
%w(accounts_id_seq developers_id_seq projects_id_seq topics_id_seq customers_id_seq orders_id_seq).each do |seq_name|
execute "SELECT setval('#{seq_name}', 100)"
end
@@ -35,7 +37,12 @@ ActiveRecord::Schema.define do
);
_SQL
- execute <<_SQL
+ execute "CREATE SCHEMA schema_1"
+ execute "CREATE DOMAIN schema_1.text AS text"
+ execute "CREATE DOMAIN schema_1.varchar AS varchar"
+ execute "CREATE DOMAIN schema_1.bpchar AS bpchar"
+
+ execute <<_SQL
CREATE TABLE geometrics (
id serial primary key,
a_point point,