#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.
This commit is contained in:
Arturo Pie
2012-10-13 23:48:37 -04:00
parent 84c37741e0
commit 3980465f26
4 changed files with 54 additions and 2 deletions

View File

@@ -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.

View File

@@ -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

View File

@@ -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

View File

@@ -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,