class Scenic::Adapters::Postgres::Views
Fetches defined views from the postgres connection. @api private
Constants
- DEPENDENT_SQL
-
Query for the dependencies between views
Attributes
Public Class Methods
Source
# File lib/scenic/adapters/postgres/views.rb, line 7 def initialize(connection) @connection = connection end
Public Instance Methods
Source
# File lib/scenic/adapters/postgres/views.rb, line 18 def all scenic_views = views_from_postgres.map(&method(:to_scenic_view)) sort(scenic_views) end
All of the views that this connection has defined, sorted according to dependencies between the views to facilitate dumping and loading.
This will include materialized views if those are supported by the connection.
@return [Array<Scenic::View>]
Private Instance Methods
Source
# File lib/scenic/adapters/postgres/views.rb, line 122 def namespaced_view_name(result) namespace, viewname = result.values_at("namespace", "viewname") if namespace != "public" "#{pg_identifier(namespace)}.#{pg_identifier(viewname)}" else pg_identifier(viewname) end end
Source
# File lib/scenic/adapters/postgres/views.rb, line 132 def pg_identifier(name) return name if /^[a-zA-Z_][a-zA-Z0-9_]*$/.match?(name) pgconn.quote_ident(name) end
Source
# File lib/scenic/adapters/postgres/views.rb, line 138 def pgconn if defined?(PG::Connection) PG::Connection else PGconn end end
Source
# File lib/scenic/adapters/postgres/views.rb, line 25 def sort(scenic_views) scenic_view_names = scenic_views.map(&:name) tsorted_views(scenic_view_names).map do |view_name| scenic_views.find do |sv| sv.name == view_name || sv.name == view_name.split(".").last end end.compact end
Source
# File lib/scenic/adapters/postgres/views.rb, line 114 def to_scenic_view(result) Scenic::View.new( name: namespaced_view_name(result), definition: result["definition"].strip, materialized: result["kind"] == "m" ) end
Source
# File lib/scenic/adapters/postgres/views.rb, line 37 def tsorted_views(views_names) views_hash = TSortableHash.new ::Scenic.database.execute(DEPENDENT_SQL).each do |relation| source_v = [ relation["source_schema"], relation["source_table"] ].compact.join(".") dependent = [ relation["dependent_schema"], relation["dependent_view"] ].compact.join(".") views_hash[dependent] ||= [] views_hash[source_v] ||= [] views_hash[dependent] << source_v views_names.delete(relation["source_table"]) views_names.delete(relation["dependent_view"]) end # after dependencies, there might be some views left # that don't have any dependencies views_names.sort.each { |v| views_hash[v] ||= [] } views_hash.tsort end
When dumping the views, their order must be topologically sorted to take into account dependencies
Source
# File lib/scenic/adapters/postgres/views.rb, line 96 def views_from_postgres connection.execute(<<-SQL) SELECT c.relname as viewname, pg_get_viewdef(c.oid) AS definition, c.relkind AS kind, n.nspname AS namespace FROM pg_class c LEFT JOIN pg_namespace n ON n.oid = c.relnamespace WHERE c.relkind IN ('m', 'v') AND c.relname NOT IN (SELECT extname FROM pg_extension) AND c.relname != 'pg_stat_statements_info' AND n.nspname = ANY (current_schemas(false)) ORDER BY c.oid SQL end