From 8a2a5651bb37a3ede88966f84864f62d827a7136 Mon Sep 17 00:00:00 2001 From: smudge Date: Wed, 17 Jan 2024 12:15:52 -0500 Subject: [PATCH 1/2] Avoid hardcoding 'public' and rely on current schema instead for naming conventions --- lib/scenic/adapters/postgres/views.rb | 6 +++++- spec/scenic/adapters/postgres_spec.rb | 2 +- spec/scenic/schema_dumper_spec.rb | 26 ++++++++++++++++++++++++-- 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/lib/scenic/adapters/postgres/views.rb b/lib/scenic/adapters/postgres/views.rb index 02b93588..29038cd6 100644 --- a/lib/scenic/adapters/postgres/views.rb +++ b/lib/scenic/adapters/postgres/views.rb @@ -43,7 +43,7 @@ def views_from_postgres def to_scenic_view(result) namespace, viewname = result.values_at "namespace", "viewname" - namespaced_viewname = if namespace != "public" + namespaced_viewname = if namespace != current_schema "#{pg_identifier(namespace)}.#{pg_identifier(viewname)}" else pg_identifier(viewname) @@ -56,6 +56,10 @@ def to_scenic_view(result) ) end + def current_schema + @current_schema ||= connection.execute("SELECT CURRENT_SCHEMA()").first["current_schema"] + end + def pg_identifier(name) return name if /^[a-zA-Z_][a-zA-Z0-9_]*$/.match?(name) diff --git a/spec/scenic/adapters/postgres_spec.rb b/spec/scenic/adapters/postgres_spec.rb index d8358a16..0e5a7557 100644 --- a/spec/scenic/adapters/postgres_spec.rb +++ b/spec/scenic/adapters/postgres_spec.rb @@ -194,7 +194,7 @@ module Adapters ActiveRecord::Base.connection.execute <<-SQL CREATE SCHEMA scenic; CREATE VIEW scenic.parents AS SELECT text 'Maarten' AS name; - SET search_path TO scenic, public; + SET search_path TO public, scenic; SQL expect(adapter.views.map(&:name)).to eq [ diff --git a/spec/scenic/schema_dumper_spec.rb b/spec/scenic/schema_dumper_spec.rb index c9f285eb..f7470c0a 100644 --- a/spec/scenic/schema_dumper_spec.rb +++ b/spec/scenic/schema_dumper_spec.rb @@ -58,16 +58,38 @@ class SearchInAHaystack < ActiveRecord::Base context "with views in non public schemas" do it "dumps a create_view including namespace for a view in the database" do view_definition = "SELECT 'needle'::text AS haystack" - Search.connection.execute "CREATE SCHEMA scenic; SET search_path TO scenic, public" + Search.connection.execute "CREATE SCHEMA scenic; SET search_path TO public, scenic" Search.connection.create_view :"scenic.searches", sql_definition: view_definition + Search.connection.create_view :"public.searches", sql_definition: view_definition stream = StringIO.new ActiveRecord::SchemaDumper.dump(Search.connection, stream) output = stream.string expect(output).to include 'create_view "scenic.searches",' + expect(output).to include 'create_view "searches",' Search.connection.drop_view :"scenic.searches" + Search.connection.drop_view :"public.searches" + end + + context 'when "public" is not the primary search path' do + it "dumps a create_view including namespace for a view in the database" do + view_definition = "SELECT 'needle'::text AS haystack" + Search.connection.execute "CREATE SCHEMA scenic; SET search_path TO scenic, public" + Search.connection.create_view :"scenic.searches", sql_definition: view_definition + Search.connection.create_view :"public.searches", sql_definition: view_definition + stream = StringIO.new + + ActiveRecord::SchemaDumper.dump(Search.connection, stream) + + output = stream.string + expect(output).to include 'create_view "searches",' + expect(output).to include 'create_view "public.searches",' + + Search.connection.drop_view :"scenic.searches" + Search.connection.drop_view :"public.searches" + end end end @@ -123,7 +145,7 @@ class SearchInAHaystack < ActiveRecord::Base it "dumps a create_view for a view in the database" do view_definition = "SELECT 'needle'::text AS haystack" Search.connection.execute( - "CREATE SCHEMA scenic; SET search_path TO scenic, public" + "CREATE SCHEMA scenic; SET search_path TO public, scenic" ) Search.connection.create_view 'scenic."search in a haystack"', sql_definition: view_definition From 6f1527103a0d7a31908fd60fd37affcf12b4d689 Mon Sep 17 00:00:00 2001 From: smudge Date: Wed, 17 Jan 2024 12:21:34 -0500 Subject: [PATCH 2/2] Combine queries, fetch current_schema alongside views --- lib/scenic/adapters/postgres/views.rb | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/lib/scenic/adapters/postgres/views.rb b/lib/scenic/adapters/postgres/views.rb index 29038cd6..b1bca423 100644 --- a/lib/scenic/adapters/postgres/views.rb +++ b/lib/scenic/adapters/postgres/views.rb @@ -28,7 +28,8 @@ def views_from_postgres c.relname as viewname, pg_get_viewdef(c.oid) AS definition, c.relkind AS kind, - n.nspname AS namespace + n.nspname AS namespace, + current_schema() AS current_schema FROM pg_class c LEFT JOIN pg_namespace n ON n.oid = c.relnamespace WHERE @@ -41,7 +42,7 @@ def views_from_postgres end def to_scenic_view(result) - namespace, viewname = result.values_at "namespace", "viewname" + namespace, viewname, current_schema = result.values_at "namespace", "viewname", "current_schema" namespaced_viewname = if namespace != current_schema "#{pg_identifier(namespace)}.#{pg_identifier(viewname)}" @@ -56,10 +57,6 @@ def to_scenic_view(result) ) end - def current_schema - @current_schema ||= connection.execute("SELECT CURRENT_SCHEMA()").first["current_schema"] - end - def pg_identifier(name) return name if /^[a-zA-Z_][a-zA-Z0-9_]*$/.match?(name)