require "pg_meta" # Extend MetaDb with a link table detection method module PgMeta class Table # True if table is a N:M link table. A N:M relation allows for multiple # relations between two records # # A table is a N:M table if # o it has a primary key named 'id' as the first column # o has two reference fields using the link field naming convention # o and nothing else # def mm_table? @mm_table ||= if columns.size != 3 false elsif columns.values.first.name != "id" || columns.values.first != primary_key_column false else referential_constraints.size == 2 && referential_constraints.values.map { |constraint| constraint.referencing_columns }.sort == [[columns.values[1]], [columns.values[2]]].sort end end # True if table is a N:N link table. A N:N relation have at most one # relation between two records. A N:N link table is also a M:M table # # A table is a N:N link table if # o it has a primary key named 'id' as the first column # o has two reference fields using the link field naming convention # o has a unique index on the two reference fields # o and nothing else # def nm_table? @nm_table ||= @mm_table && begin expected_columns = referential_constraints.values.map(&:columns).flatten.sort unique_constraints.values.any? { |constraint| expected_columns == constraint.columns.sort } end end def path schema.name + "." + name end end class Column def path() table.path + "." + name end end end