class PGExaminer::Result

Attributes

pg_attrdef[R]
pg_attribute[R]
pg_class[R]
pg_constraint[R]
pg_extension[R]
pg_index[R]
pg_language[R]
pg_namespace[R]
pg_proc[R]
pg_trigger[R]
pg_type[R]

Public Class Methods

new(connection) click to toggle source
# File lib/pg_examiner/result.rb, line 19
def initialize(connection)
  @conn = connection
  load_schema
end

Public Instance Methods

diffable_lists() click to toggle source
# File lib/pg_examiner/result.rb, line 24
def diffable_lists
  {
    "schemas"    => "schemas",
    "extensions" => "extensions",
    "languages"  => "languages",
  }
end
extensions() click to toggle source
# File lib/pg_examiner/result.rb, line 36
def extensions
  @extensions ||= @pg_extension.map{|row| Extension.new(self, row)}.sort_by(&:name)
end
inspect() click to toggle source
# File lib/pg_examiner/result.rb, line 44
def inspect
  "#<#{self.class} @schemas=#{@schemas.inspect}, @extensions=#{@extensions.inspect}>"
end
languages() click to toggle source
# File lib/pg_examiner/result.rb, line 40
def languages
  @languages ||= @pg_language.map{|row| Language.new(self, row)}.sort_by(&:name)
end
schemas() click to toggle source
# File lib/pg_examiner/result.rb, line 32
def schemas
  @schemas ||= @pg_namespace.map{|row| Schema.new(self, row)}.sort_by(&:name)
end

Private Instance Methods

execute(*args) click to toggle source
# File lib/pg_examiner/result.rb, line 50
def execute(*args)
  @conn.async_exec(*args).to_a
end
load_schema() click to toggle source
# File lib/pg_examiner/result.rb, line 54
    def load_schema
      # Get all relevant schemas/namespaces, which includes public but not
      # information_schema or system schemas, which are prefixed with pg_. It
      # wouldn't be a good practice for anyone to name a custom schema
      # starting with pg_ anyway.
      @pg_namespace = execute <<-SQL
        SELECT oid, nspname AS name
        FROM pg_namespace
        WHERE nspname != 'information_schema'
        AND nspname NOT LIKE 'pg_%'
      SQL

      @pg_class = load_table @pg_namespace.map{|ns| ns['oid']}, <<-SQL
        SELECT oid, relname AS name, relkind, relpersistence, reloptions, relnamespace, relacl
        FROM pg_class
        WHERE relnamespace IN (?)
      SQL

      @pg_attribute = load_table @pg_class.map{|ns| ns['oid']}, <<-SQL
        SELECT atttypid, attname AS name, attndims, attnotnull, atttypmod, attrelid, atthasdef, attnum
        FROM pg_attribute
        WHERE attrelid IN (?)
        AND attnum > 0       -- No system columns
        AND NOT attisdropped -- Still active
      SQL

      @pg_type = execute <<-SQL
        SELECT oid, typname AS name
        FROM pg_type
      SQL

      @pg_index = load_table @pg_class.map{|ns| ns['oid']}, <<-SQL
        SELECT i.indexrelid, c.relname AS name, i.indrelid, i.indkey, indisunique, indisprimary,
          pg_get_expr(i.indpred, i.indrelid) AS filter,
          pg_get_expr(i.indexprs, i.indrelid) AS expression
        FROM pg_index i
        JOIN pg_class c ON c.oid = i.indexrelid
        WHERE c.oid IN (?)
      SQL

      @pg_constraint = load_table @pg_class.map{|ns| ns['oid']}, <<-SQL
        SELECT oid, conname AS name, conrelid, contype,
          condeferrable, condeferred, convalidated,
          contypid, conindid, confrelid, confupdtype, confdeltype, confmatchtype,
          connoinherit, conkey, confkey, pg_get_expr(conbin, conrelid) AS check_def
        FROM pg_constraint c
        WHERE conrelid IN (?)
      SQL

      @pg_trigger = load_table @pg_class.map{|ns| ns['oid']}, <<-SQL
        SELECT oid, tgname AS name, tgrelid, tgtype, tgfoid
        FROM pg_trigger
        WHERE tgrelid IN (?)
        AND NOT tgisinternal -- Ignore foreign key and unique index triggers, which have unpredictable names.
      SQL

      @pg_attrdef = execute <<-SQL
        SELECT oid, adrelid, adnum, pg_get_expr(adbin, adrelid) AS default
        FROM pg_attrdef
      SQL

      # Handle change to system table in PG 11.
      if @conn.server_version >= 110000
        @pg_proc = load_table @pg_namespace.map{|ns| ns['oid']}, <<-SQL
          SELECT oid, proname AS name, pronamespace, proargtypes, prorettype, proargmodes, prolang, pg_get_functiondef(oid) AS definition
          FROM pg_proc
          WHERE pronamespace IN (?)
          AND prokind <> 'a' -- prevent pg_get_functiondef() from throwing errors on aggregate functions.
        SQL
      else
        @pg_proc = load_table @pg_namespace.map{|ns| ns['oid']}, <<-SQL
          SELECT oid, proname AS name, pronamespace, proargtypes, prorettype, proargmodes, prolang, pg_get_functiondef(oid) AS definition
          FROM pg_proc
          WHERE pronamespace IN (?)
          AND NOT proisagg -- prevent pg_get_functiondef() from throwing errors on aggregate functions.
        SQL
      end

      @pg_extension = execute <<-SQL
        SELECT extname AS name, extnamespace, extversion
        FROM pg_extension
      SQL

      @pg_language = execute <<-SQL
        SELECT oid, lanname AS name
        FROM pg_language
      SQL
    end
load_table(oids, sql) click to toggle source
# File lib/pg_examiner/result.rb, line 143
def load_table(oids, sql)
  if oids.any?
    execute sql.gsub(/\?/, oids.map{|oid| "'#{oid}'"}.join(', '))
  else
    []
  end
end