aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--activerecord/CHANGELOG.md12
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb5
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb6
-rw-r--r--activerecord/test/cases/adapters/postgresql/schema_test.rb54
4 files changed, 67 insertions, 10 deletions
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md
index 60fd8b85b9..ec3ec06c2b 100644
--- a/activerecord/CHANGELOG.md
+++ b/activerecord/CHANGELOG.md
@@ -1,3 +1,15 @@
+* PostgreSQL, `create_schema`, `drop_schema` and `rename_table` now quote
+ schema names.
+
+ Fixes #21418.
+
+ Example:
+
+ create_schema("my.schema")
+ # CREATE SCHEMA "my.schema";
+
+ *Yves Senn*
+
* PostgreSQL, add `:if_exists` option to `#drop_schema`. This makes it
possible to drop a schema that might exist without raising an exception if
it doesn't.
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb b/activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb
index f175730551..d5879ea7df 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb
@@ -31,6 +31,11 @@ module ActiveRecord
Utils.extract_schema_qualified_name(name.to_s).quoted
end
+ # Quotes schema names for use in SQL queries.
+ def quote_schema_name(name)
+ PGconn.quote_ident(name)
+ end
+
def quote_table_name_for_assignment(table, attr)
quote_column_name(attr)
end
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb b/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb
index 21268b63b1..a3fc8fbc51 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb
@@ -210,12 +210,12 @@ module ActiveRecord
# Creates a schema for the given schema name.
def create_schema schema_name
- execute "CREATE SCHEMA #{schema_name}"
+ execute "CREATE SCHEMA #{quote_schema_name(schema_name)}"
end
# Drops the schema for the given schema name.
def drop_schema(schema_name, options = {})
- execute "DROP SCHEMA#{' IF EXISTS' if options[:if_exists]} #{schema_name} CASCADE"
+ execute "DROP SCHEMA#{' IF EXISTS' if options[:if_exists]} #{quote_schema_name(schema_name)} CASCADE"
end
# Sets the schema search path to a string of comma-separated schema names.
@@ -376,7 +376,7 @@ module ActiveRecord
new_seq = "#{new_name}_#{pk}_seq"
idx = "#{table_name}_pkey"
new_idx = "#{new_name}_pkey"
- execute "ALTER TABLE #{quote_table_name(seq)} RENAME TO #{quote_table_name(new_seq)}"
+ execute "ALTER TABLE #{seq.quoted} RENAME TO #{quote_table_name(new_seq)}"
execute "ALTER INDEX #{quote_table_name(idx)} RENAME TO #{quote_table_name(new_idx)}"
end
diff --git a/activerecord/test/cases/adapters/postgresql/schema_test.rb b/activerecord/test/cases/adapters/postgresql/schema_test.rb
index 6edd3c4868..ea7e5ac587 100644
--- a/activerecord/test/cases/adapters/postgresql/schema_test.rb
+++ b/activerecord/test/cases/adapters/postgresql/schema_test.rb
@@ -2,7 +2,17 @@ require "cases/helper"
require 'models/default'
require 'support/schema_dumping_helper'
+module PGSchemaHelper
+ def with_schema_search_path(schema_search_path)
+ @connection.schema_search_path = schema_search_path
+ yield if block_given?
+ ensure
+ @connection.schema_search_path = "'$user', public"
+ end
+end
+
class SchemaTest < ActiveRecord::PostgreSQLTestCase
+ include PGSchemaHelper
self.use_transactional_tests = false
SCHEMA_NAME = 'test_schema'
@@ -415,13 +425,6 @@ class SchemaTest < ActiveRecord::PostgreSQLTestCase
end
end
- def with_schema_search_path(schema_search_path)
- @connection.schema_search_path = schema_search_path
- yield if block_given?
- ensure
- @connection.schema_search_path = "'$user', public"
- end
-
def do_dump_index_tests_for_schema(this_schema_name, first_index_column_name, second_index_column_name, third_index_column_name, fourth_index_column_name)
with_schema_search_path(this_schema_name) do
indexes = @connection.indexes(TABLE_NAME).sort_by(&:name)
@@ -530,3 +533,40 @@ class DefaultsUsingMultipleSchemasAndDomainTest < ActiveRecord::PostgreSQLTestCa
assert_equal "foo'::bar", Default.new.string_col
end
end
+
+class SchemaWithDotsTest < ActiveRecord::PostgreSQLTestCase
+ include PGSchemaHelper
+ self.use_transactional_tests = false
+
+ setup do
+ @connection = ActiveRecord::Base.connection
+ @connection.create_schema "my.schema"
+ end
+
+ teardown do
+ @connection.drop_schema "my.schema", if_exists: true
+ end
+
+ test "rename_table" do
+ with_schema_search_path('"my.schema"') do
+ @connection.create_table :posts
+ @connection.rename_table :posts, :articles
+ assert_equal ["articles"], @connection.tables
+ end
+ end
+
+ test "Active Record basics" do
+ with_schema_search_path('"my.schema"') do
+ @connection.create_table :articles do |t|
+ t.string :title
+ end
+ article_class = Class.new(ActiveRecord::Base) do
+ self.table_name = '"my.schema".articles'
+ end
+
+ article_class.create!(title: "zOMG, welcome to my blorgh!")
+ welcome_article = article_class.last
+ assert_equal "zOMG, welcome to my blorgh!", welcome_article.title
+ end
+ end
+end