class DbSchema::Reader::Postgres
Constants
- COLUMNS_QUERY
- CONSTRAINTS_QUERY
- ENUMS_QUERY
- EXPRESSION_INDEXES_QUERY
- EXTENSIONS_QUERY
- INDEXES_QUERY
- TABLES_QUERY
- VERSION
Attributes
connection[R]
Public Class Methods
new(connection)
click to toggle source
# File lib/db_schema/reader/postgres.rb, line 110 def initialize(connection) @connection = connection end
Public Instance Methods
read_enums()
click to toggle source
# File lib/db_schema/reader/postgres.rb, line 136 def read_enums connection[ENUMS_QUERY].map do |enum_data| Definitions::Enum.new(enum_data[:name].to_sym, enum_data[:values].map(&:to_sym)) end end
read_extensions()
click to toggle source
# File lib/db_schema/reader/postgres.rb, line 142 def read_extensions connection[EXTENSIONS_QUERY].map do |extension_data| Definitions::Extension.new(extension_data[:extname].to_sym) end end
read_schema()
click to toggle source
# File lib/db_schema/reader/postgres.rb, line 114 def read_schema Definitions::Schema.new( tables: read_tables, enums: read_enums, extensions: read_extensions ) end
read_tables()
click to toggle source
# File lib/db_schema/reader/postgres.rb, line 122 def read_tables checks_data, foreign_keys_data = constraints_data table_names.map do |table_name| Table.new( table_name.to_sym, columns_data[table_name], indexes_data[table_name], checks_data[table_name], foreign_keys_data[table_name] ).definition end end
Private Instance Methods
columns_data()
click to toggle source
# File lib/db_schema/reader/postgres.rb, line 153 def columns_data @columns_data ||= connection[COLUMNS_QUERY].to_a.group_by do |column| column[:table_name] end end
constraints_data()
click to toggle source
# File lib/db_schema/reader/postgres.rb, line 217 def constraints_data checks = Hash.new { |h, k| h[k] = [] } foreign_keys = Hash.new { |h, k| h[k] = [] } connection[CONSTRAINTS_QUERY].each do |constraint| case constraint[:type] when 'c' checks[constraint[:table_name]] << { name: constraint[:name], condition: constraint[:condition] } when 'f' fields = constraint[:conkey].map do |position| get_field_name(constraint[:table_name], position) end keys = constraint[:confkey].map do |position| get_field_name(constraint[:referenced], position) end pkey = indexes_data.fetch(constraint[:referenced]).find { |index| index[:primary] } keys = [] if !pkey.nil? && keys == pkey.fetch(:columns) # this foreign key references a primary key foreign_keys[constraint[:table_name]] << { name: constraint[:name], referenced: constraint[:referenced], fields: fields, keys: keys, on_update: constraint[:on_update], on_delete: constraint[:on_delete], deferrable: constraint[:deferrable] } else raise "Unknown constraint type #{constraint[:type].inspect}" end end [checks, foreign_keys] end
get_field_name(table, position)
click to toggle source
# File lib/db_schema/reader/postgres.rb, line 257 def get_field_name(table, position) columns_data.fetch(table).find do |column| column[:pos] == position end.fetch(:name).to_sym end
index_expressions_data(indexes_data)
click to toggle source
# File lib/db_schema/reader/postgres.rb, line 186 def index_expressions_data(indexes_data) all_positions, max_position = {}, 0 indexes_data.each do |index_data| positions = index_data[:column_positions] expression_positions = positions.each_index.select do |i| positions[i].zero? end if expression_positions.any? all_positions[index_data[:index_oid]] = expression_positions max_position = [max_position, expression_positions.max].max end end if all_positions.any? connection[ EXPRESSION_INDEXES_QUERY, Sequel.pg_array(all_positions.keys), Sequel.pg_array((1..max_position.succ).to_a) ].each_with_object({}) do |index_data, indexes_data| index_id = index_data[:index_id] expressions = all_positions[index_id].map { |pos| index_data[:definitions][pos] } indexes_data[index_id] = expressions end else {} end end
indexes_data()
click to toggle source
# File lib/db_schema/reader/postgres.rb, line 159 def indexes_data @indexes_data ||= begin raw_data = connection[INDEXES_QUERY].map do |index_data| index_data.merge( column_positions: index_data[:column_positions].split(' ').map(&:to_i), index_options: index_data[:index_options].split(' ').map(&:to_i) ) end expressions_data = index_expressions_data(raw_data) raw_data.map do |index_data| columns = index_data[:column_positions].map do |position| if position.zero? expressions_data.fetch(index_data[:index_oid]).shift else get_field_name(index_data[:table_name], position) end end index_data.delete(:index_oid) index_data.delete(:column_positions) index_data.merge(columns: columns) end.group_by { |index| index[:table_name] }.tap { |h| h.default = [] } end end
table_names()
click to toggle source
# File lib/db_schema/reader/postgres.rb, line 149 def table_names @table_names ||= connection[TABLES_QUERY].to_a.map { |row| row[:table_name] } end