Module: DbSchema::Reader::Postgres
- Defined in:
- lib/db_schema/reader.rb
Constant Summary collapse
- DEFAULT_VALUE =
/\A(('(?<string>.*)')|(?<float>\d+\.\d+)|(?<integer>\d+)|(?<boolean>true|false)|((?<function>[A-Za-z_]+)\(\)))/- COLUMN_NAMES_QUERY =
<<-SQL.freeze SELECT c.column_name AS name, c.ordinal_position AS pos, c.column_default AS default, c.is_nullable AS null, c.data_type AS type, c.udt_name AS custom_type_name, c.character_maximum_length AS char_length, c.numeric_precision AS num_precision, c.numeric_scale AS num_scale, c.datetime_precision AS dt_precision, c.interval_type, e.data_type AS element_type FROM information_schema.columns AS c LEFT JOIN information_schema.element_types AS e ON e.object_catalog = c.table_catalog AND e.object_schema = c.table_schema AND e.object_name = c.table_name AND e.object_type = 'TABLE' AND e.collection_type_identifier = c.dtd_identifier WHERE c.table_schema = 'public' AND c.table_name = ? SQL
- CONSTRAINTS_QUERY =
<<-SQL.freeze SELECT conname AS name, pg_get_expr(conbin, conrelid, true) AS condition FROM pg_constraint, pg_class WHERE conrelid = pg_class.oid AND relname = ? AND contype = 'c' SQL
- INDICES_QUERY =
<<-SQL.freeze SELECT relname AS name, indkey AS column_positions, indisunique AS unique, indoption AS index_options, pg_get_expr(indpred, indrelid, true) AS condition, amname AS index_type, indexrelid AS index_oid FROM pg_class, pg_index LEFT JOIN pg_opclass ON pg_opclass.oid = ANY(pg_index.indclass::int[]) LEFT JOIN pg_am ON pg_am.oid = pg_opclass.opcmethod WHERE pg_class.oid = pg_index.indexrelid AND pg_class.oid IN ( SELECT indexrelid FROM pg_index, pg_class WHERE pg_class.relname = ? AND pg_class.oid = pg_index.indrelid AND indisprimary != 't' ) GROUP BY name, column_positions, indisunique, index_options, condition, index_type, index_oid SQL
- EXPRESSION_INDICES_QUERY =
<<-SQL.freeze WITH index_ids AS (SELECT unnest(?) AS index_id), elements AS (SELECT unnest(?) AS element) SELECT index_id, array_agg(pg_get_indexdef(index_id, element, 't')) AS definitions FROM index_ids, elements GROUP BY index_id; SQL
- ENUMS_QUERY =
<<-SQL.freeze SELECT t.typname AS name, array_agg(e.enumlabel ORDER BY e.enumsortorder) AS values FROM pg_enum AS e JOIN pg_type AS t ON t.oid = e.enumtypid GROUP BY name SQL
- EXTENSIONS_QUERY =
<<-SQL.freeze SELECT extname FROM pg_extension WHERE extname != 'plpgsql' SQL
Class Method Summary collapse
Class Method Details
.indices_data_for(table_name) ⇒ Object
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 |
# File 'lib/db_schema/reader.rb', line 149 def indices_data_for(table_name) column_names = DbSchema.connection[COLUMN_NAMES_QUERY, table_name.to_s].reduce({}) do |names, column| names.merge(column[:pos] => column[:name].to_sym) end indices_data = DbSchema.connection[INDICES_QUERY, table_name.to_s].to_a expressions_data = index_expressions_data(indices_data) indices_data.map do |index| positions = index[:column_positions].split(' ').map(&:to_i) = index[:index_options].split(' ').map(&:to_i) columns = positions.zip().map do |column_position, | = case when 0 {} when 3 { order: :desc } when 2 { nulls: :first } when 1 { order: :desc, nulls: :last } end if column_position.zero? expression = expressions_data.fetch(index[:index_oid]).shift DbSchema::Definitions::Index::Expression.new(expression, **) else DbSchema::Definitions::Index::TableField.new(column_names.fetch(column_position), **) end end { name: index[:name].to_sym, columns: columns, unique: index[:unique], type: index[:index_type].to_sym, condition: index[:condition] } end end |
.read_schema ⇒ Object
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
# File 'lib/db_schema/reader.rb', line 106 def read_schema enums = DbSchema.connection[ENUMS_QUERY].map do |enum_data| Definitions::Enum.new(enum_data[:name].to_sym, enum_data[:values].map(&:to_sym)) end extensions = DbSchema.connection[EXTENSIONS_QUERY].map do |extension_data| Definitions::Extension.new(extension_data[:extname].to_sym) end tables = DbSchema.connection.tables.map do |table_name| primary_key_name = DbSchema.connection.primary_key(table_name) fields = DbSchema.connection[COLUMN_NAMES_QUERY, table_name.to_s].map do |column_data| build_field(column_data, primary_key: column_data[:name] == primary_key_name) end indices = indices_data_for(table_name).map do |index_data| Definitions::Index.new(index_data) end.sort_by(&:name) foreign_keys = DbSchema.connection.foreign_key_list(table_name).map do |foreign_key_data| build_foreign_key(foreign_key_data) end checks = DbSchema.connection[CONSTRAINTS_QUERY, table_name.to_s].map do |check_data| Definitions::CheckConstraint.new( name: check_data[:name].to_sym, condition: check_data[:condition] ) end Definitions::Table.new( table_name, fields: fields, indices: indices, checks: checks, foreign_keys: foreign_keys ) end enums + extensions + tables end |