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 83310233f0259..69f797da3a66f 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb @@ -86,7 +86,7 @@ def data_sources # :nodoc SELECT c.relname FROM pg_class c LEFT JOIN pg_namespace n ON n.oid = c.relnamespace - WHERE c.relkind IN ('r', 'v','m') -- (r)elation/table, (v)iew, (m)aterialized view + WHERE c.relkind IN ('r','v','m') -- (r)elation/table, (v)iew, (m)aterialized view AND n.nspname = ANY (current_schemas(false)) SQL end @@ -108,13 +108,13 @@ def data_source_exists?(name) name = Utils.extract_schema_qualified_name(name.to_s) return false unless name.identifier - select_value(<<-SQL, "SCHEMA").to_i > 0 - SELECT COUNT(*) + select_values(<<-SQL, "SCHEMA").any? + SELECT c.relname FROM pg_class c LEFT JOIN pg_namespace n ON n.oid = c.relnamespace WHERE c.relkind IN ('r','v','m') -- (r)elation/table, (v)iew, (m)aterialized view - AND c.relname = '#{name.identifier}' - AND n.nspname = #{name.schema ? "'#{name.schema}'" : 'ANY (current_schemas(false))'} + AND c.relname = #{quote(name.identifier)} + AND n.nspname = #{name.schema ? quote(name.schema) : "ANY (current_schemas(false))"} SQL end @@ -137,8 +137,8 @@ def view_exists?(view_name) # :nodoc: FROM pg_class c LEFT JOIN pg_namespace n ON n.oid = c.relnamespace WHERE c.relkind IN ('v','m') -- (v)iew, (m)aterialized view - AND c.relname = '#{name.identifier}' - AND n.nspname = #{name.schema ? "'#{name.schema}'" : 'ANY (current_schemas(false))'} + AND c.relname = #{quote(name.identifier)} + AND n.nspname = #{name.schema ? quote(name.schema) : "ANY (current_schemas(false))"} SQL end @@ -441,7 +441,7 @@ def primary_keys(table_name) # :nodoc: WITH pk_constraint AS ( SELECT conrelid, unnest(conkey) AS connum FROM pg_constraint WHERE contype = 'p' - AND conrelid = '#{quote_table_name(table_name)}'::regclass + AND conrelid = #{quote(quote_table_name(table_name))}::regclass ), cons AS ( SELECT conrelid, connum, row_number() OVER() AS rownum FROM pk_constraint ) diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb index a33e64883ee05..acd1eeace76d4 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb @@ -750,7 +750,7 @@ def column_definitions(table_name) # :nodoc: col_description(a.attrelid, a.attnum) AS comment FROM pg_attribute a LEFT JOIN pg_attrdef d ON a.attrelid = d.adrelid AND a.attnum = d.adnum - WHERE a.attrelid = '#{quote_table_name(table_name)}'::regclass + WHERE a.attrelid = #{quote(quote_table_name(table_name))}::regclass AND a.attnum > 0 AND NOT a.attisdropped ORDER BY a.attnum end_sql diff --git a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb index e2b534b511dee..ebeac425d02b7 100644 --- a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb @@ -530,10 +530,12 @@ def translate_exception(exception, message) def table_structure_with_collation(table_name, basic_structure) collation_hash = {} - sql = "SELECT sql FROM - (SELECT * FROM sqlite_master UNION ALL - SELECT * FROM sqlite_temp_master) - WHERE type='table' and name='#{ table_name }' \;" + sql = <<-SQL + SELECT sql FROM + (SELECT * FROM sqlite_master UNION ALL + SELECT * FROM sqlite_temp_master) + WHERE type = 'table' AND name = #{quote(table_name)} + SQL # Result will have following sample string # CREATE TABLE "users" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, diff --git a/activerecord/test/cases/adapter_test.rb b/activerecord/test/cases/adapter_test.rb index 8fa0645b0f68d..cfbc8ab9423f5 100644 --- a/activerecord/test/cases/adapter_test.rb +++ b/activerecord/test/cases/adapter_test.rb @@ -42,8 +42,10 @@ def test_tables def test_table_exists? ActiveSupport::Deprecation.silence do assert @connection.table_exists?("accounts") - assert !@connection.table_exists?("nonexistingtable") - assert !@connection.table_exists?(nil) + assert @connection.table_exists?(:accounts) + assert_not @connection.table_exists?("nonexistingtable") + assert_not @connection.table_exists?("'") + assert_not @connection.table_exists?(nil) end end @@ -63,6 +65,7 @@ def test_data_source_exists? assert @connection.data_source_exists?("accounts") assert @connection.data_source_exists?(:accounts) assert_not @connection.data_source_exists?("nonexistingtable") + assert_not @connection.data_source_exists?("'") assert_not @connection.data_source_exists?(nil) end diff --git a/activerecord/test/cases/view_test.rb b/activerecord/test/cases/view_test.rb index 0e38cee334d4c..1f326d4b39845 100644 --- a/activerecord/test/cases/view_test.rb +++ b/activerecord/test/cases/view_test.rb @@ -11,20 +11,21 @@ module ViewBehavior end class Ebook < ActiveRecord::Base + self.table_name = "ebooks'" self.primary_key = "id" end def setup super @connection = ActiveRecord::Base.connection - create_view "ebooks", <<-SQL + create_view "ebooks'", <<-SQL SELECT id, name, status FROM books WHERE format = 'ebook' SQL end def teardown super - drop_view "ebooks" + drop_view "ebooks'" end def test_reading @@ -66,15 +67,20 @@ def test_attributes def test_does_not_assume_id_column_as_primary_key model = Class.new(ActiveRecord::Base) do - self.table_name = "ebooks" + self.table_name = "ebooks'" end assert_nil model.primary_key end def test_does_not_dump_view_as_table - schema = dump_table_schema "ebooks" - assert_no_match %r{create_table "ebooks"}, schema + schema = dump_table_schema "ebooks'" + assert_no_match %r{create_table "ebooks'"}, schema end + + private + def quote_table_name(name) + @connection.quote_table_name(name) + end end if ActiveRecord::Base.connection.supports_views? @@ -83,11 +89,11 @@ class ViewWithPrimaryKeyTest < ActiveRecord::TestCase private def create_view(name, query) - @connection.execute "CREATE VIEW #{name} AS #{query}" + @connection.execute "CREATE VIEW #{quote_table_name(name)} AS #{query}" end def drop_view(name) - @connection.execute "DROP VIEW #{name}" if @connection.view_exists? name + @connection.execute "DROP VIEW #{quote_table_name(name)}" if @connection.view_exists? name end end @@ -206,11 +212,11 @@ class MaterializedViewTest < ActiveRecord::PostgreSQLTestCase private def create_view(name, query) - @connection.execute "CREATE MATERIALIZED VIEW #{name} AS #{query}" + @connection.execute "CREATE MATERIALIZED VIEW #{quote_table_name(name)} AS #{query}" end def drop_view(name) - @connection.execute "DROP MATERIALIZED VIEW #{name}" if @connection.view_exists? name + @connection.execute "DROP MATERIALIZED VIEW #{quote_table_name(name)}" if @connection.view_exists? name end end end