Permalink
Browse files

Support multiple schemas in table names for postgresql [#390 state:re…

…solved]

Signed-off-by: Pratik Naik <pratiknaik@gmail.com>
  • Loading branch information...
maxlapshin authored and lifo committed Apr 4, 2009
1 parent fc2421b commit 60601234708b34c81dcd6a58a0cad79a7520ce10
@@ -392,9 +392,28 @@ def quote_string(s) #:nodoc:
quote_string(s)
end
+ # Checks the following cases:
+ #
+ # - table_name
+ # - "table.name"
+ # - schema_name.table_name
+ # - schema_name."table.name"
+ # - "schema.name".table_name
+ # - "schema.name"."table.name"
+ def quote_table_name(name)
+ schema, name_part = extract_pg_identifier_from_name(name.to_s)
+
+ unless name_part
+ quote_column_name(schema)
+ else
+ table_name, name_part = extract_pg_identifier_from_name(name_part)
+ "#{quote_column_name(schema)}.#{quote_column_name(table_name)}"
+ end
+ end
+
# Quotes column names for use in SQL queries.
def quote_column_name(name) #:nodoc:
- %("#{name}")
+ PGconn.quote_ident(name.to_s)
@tekkub

tekkub May 1, 2009

This change is throwing an error for me. I'm using the postgres-pr (0.6.1) gem.

undefined method `quote_ident' for PGconn:Class
end
# Quote date/time values for use in SQL input. Includes microseconds
@@ -1045,6 +1064,16 @@ def column_definitions(table_name) #:nodoc:
ORDER BY a.attnum
end_sql
end
+
+ def extract_pg_identifier_from_name(name)
+ match_data = name[0,1] == '"' ? name.match(/\"([^\"]+)\"/) : name.match(/([^\.]+)/)
+
+ if match_data
+ rest = name[match_data[0].length..-1]
+ rest = rest[1..-1] if rest[0,1] == "."
+ [match_data[1], (rest.length > 0 ? rest : nil)]
+ end
+ end
end
end
end
@@ -18,9 +18,22 @@ class SchemaTest < ActiveRecord::TestCase
'moment timestamp without time zone default now()'
]
+ class Thing1 < ActiveRecord::Base
+ set_table_name "test_schema.things"
+ end
+
+ class Thing2 < ActiveRecord::Base
+ set_table_name "test_schema2.things"
+ end
+
+ class Thing3 < ActiveRecord::Base
+ set_table_name 'test_schema."things.table"'
+ end
+
def setup
@connection = ActiveRecord::Base.connection
@connection.execute "CREATE SCHEMA #{SCHEMA_NAME} CREATE TABLE #{TABLE_NAME} (#{COLUMNS.join(',')})"
+ @connection.execute "CREATE TABLE #{SCHEMA_NAME}.\"#{TABLE_NAME}.table\" (#{COLUMNS.join(',')})"
@connection.execute "CREATE SCHEMA #{SCHEMA2_NAME} CREATE TABLE #{TABLE_NAME} (#{COLUMNS.join(',')})"
@connection.execute "CREATE INDEX #{INDEX_A_NAME} ON #{SCHEMA_NAME}.#{TABLE_NAME} USING btree (#{INDEX_A_COLUMN});"
@connection.execute "CREATE INDEX #{INDEX_A_NAME} ON #{SCHEMA2_NAME}.#{TABLE_NAME} USING btree (#{INDEX_A_COLUMN});"
@@ -47,6 +60,37 @@ def test_with_schema_search_path
end
end
+
+ def test_proper_encoding_of_table_name
+ assert_equal '"table_name"', @connection.quote_table_name('table_name')
+ assert_equal '"table.name"', @connection.quote_table_name('"table.name"')
+ assert_equal '"schema_name"."table_name"', @connection.quote_table_name('schema_name.table_name')
+ assert_equal '"schema_name"."table.name"', @connection.quote_table_name('schema_name."table.name"')
+ assert_equal '"schema.name"."table_name"', @connection.quote_table_name('"schema.name".table_name')
+ assert_equal '"schema.name"."table.name"', @connection.quote_table_name('"schema.name"."table.name"')
+ end
+
+ def test_classes_with_qualified_schema_name
+ assert_equal 0, Thing1.count
+ assert_equal 0, Thing2.count
+ assert_equal 0, Thing3.count
+
+ Thing1.create(:id => 1, :name => "thing1", :email => "thing1@localhost", :moment => Time.now)
+ assert_equal 1, Thing1.count
+ assert_equal 0, Thing2.count
+ assert_equal 0, Thing3.count
+
+ Thing2.create(:id => 1, :name => "thing1", :email => "thing1@localhost", :moment => Time.now)
+ assert_equal 1, Thing1.count
+ assert_equal 1, Thing2.count
+ assert_equal 0, Thing3.count
+
+ Thing3.create(:id => 1, :name => "thing1", :email => "thing1@localhost", :moment => Time.now)
+ assert_equal 1, Thing1.count
+ assert_equal 1, Thing2.count
+ assert_equal 1, Thing3.count
+ end
+
def test_raise_on_unquoted_schema_name
assert_raise(ActiveRecord::StatementInvalid) do
with_schema_search_path '$user,public'

6 comments on commit 6060123

Contributor

wallace replied May 21, 2009

I'm getting an error also: http://gist.github.com/115477 This is with gem postgres (0.7.9.2008.01.28).

Contributor

wallace replied May 21, 2009

tekkub: try gem install pg

Contributor

wallace replied May 21, 2009

tekkub: try 'gem install pg'

Contributor

njakobsen replied Jun 10, 2009

I have the same problem, and I'm using the same postgres-pr 0.6.1 gem. However, colleague of mine is running the same gem with the same Rails Application, and can migrate without any problems.

I work on Windows Vista. After update to Rails 2.3.3 I had the same problem with the "postgres-pr" gem. So I installed newer "pg" gem which has the problematic quote_ident method implemented. For some reason the new gem didn't work. After googling the problem I've copied ssleay32.dll and libeay32.dll from Postgresql bin directory to Ruby bin dir. And as for now the "pg" gem works.

If you are having problems with "undefined method 'quote_ident' for PGConn:Class", install the "pg" gem (version 0.8.x) and everything should work.

Please sign in to comment.