Quote table name properly
If does not quote table name properly, invalid SQL is generated.
This commit is contained in:
parent
e10e3c7da2
commit
c5bcbb0914
@ -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
|
||||
)
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user