Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ end

## Other options

### indexes_after_tables

You can optionally have indexes following the respective tables setting `indexes_after_tables`:

```ruby
Expand All @@ -61,6 +63,8 @@ CREATE INDEX index_users_on_tentant_id ON public.users USING btree (tenant_id);
CREATE UNIQUE INDEX index_users_on_email ON public.users USING btree (email);
```

### order_column_definitions

To enable sorting the table column definitions alphabetically, discarding the actual order provided by `pg_dump`, set `order_column_definitions`:

```ruby
Expand All @@ -69,6 +73,8 @@ Rails.application.configure do
end
```

### order_schema_migrations_values

You can have the schema_migrations values reorganized to prevent merge conflicts by setting `order_schema_migrations_values`:

```ruby
Expand All @@ -87,14 +93,26 @@ INSERT INTO "schema_migrations" (version) VALUES
;
```

### keep_extensions

By default the gem will remove [some extensions](https://github.com/ghiculescu/activerecord-clean-db-structure/blob/c9551391476a5e7a08ff314501af89baddcf669a/lib/activerecord-clean-db-structure/clean_dump.rb#L24) that typically aren't needed in structure dumps. You can choose to keep all, or just some, of those extensions:

```ruby
Rails.application.configure do
config.activerecord_clean_db_structure.keep_extensions = :all

# This does the same thing as :all. You can choose which optional extensions to keep.
config.activerecord_clean_db_structure.keep_extensions = ["pg_stat_statements", "pg_buffercache"]
config.activerecord_clean_db_structure.keep_extensions = ['pg_stat_statements', 'pg_buffercache']
end
```

### ignore_schmeas

You can ignore specific schemas, for example when dumping from a database copy that is integrated with pganalyze and has helper functions:

```ruby
Rails.application.configure do
config.activerecord_clean_db_structure.ignore_schemas = ['pganalyze']
end
```

Expand Down
30 changes: 23 additions & 7 deletions lib/activerecord-clean-db-structure/clean_dump.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@ def initialize(dump, options = {})
def run
clean_partition_tables # Must be first because it makes assumptions about string format
clean
clean_ignored_schemas
clean_inherited_tables
clean_options
clean_schema_comments
end

def clean
Expand Down Expand Up @@ -44,7 +46,7 @@ def clean
dump.gsub!(/^COMMENT ON EXTENSION .*/, '')

# Remove useless, version-specific parts of comments
dump.gsub!(/^-- (.*); Schema: ([\w\.]+|-); Owner: -.*/, '-- \1')
dump.gsub!(/^-- (.*); Owner: -.*/, '-- \1')

# Remove useless comment lines
dump.gsub!(/^--$/, '')
Expand All @@ -61,27 +63,36 @@ def clean
dump.gsub!(/^ALTER SEQUENCE [\w\.]+_id_seq OWNED BY .*;$/, '')
dump.gsub!(/^ALTER TABLE ONLY [\w\.]+ ALTER COLUMN id SET DEFAULT nextval\('[\w\.]+_id_seq'::regclass\);$/, '')
dump.gsub!(/^ALTER TABLE ONLY [\w\.]+\s+ADD CONSTRAINT [\w\.]+_pkey PRIMARY KEY \(id\);$/, '')
dump.gsub!(/^-- Name: (\w+\s+)?id; Type: DEFAULT$/, '')
dump.gsub!(/^-- Name: (\w+\s+)?id; Type: DEFAULT; Schema: \w+$/, '')
dump.gsub!(/^-- .*_id_seq; Type: SEQUENCE.*/, '')
dump.gsub!(/^-- Name: (\w+\s+)?\w+_pkey; Type: CONSTRAINT$/, '')
dump.gsub!(/^-- Name: (\w+\s+)?\w+_pkey; Type: CONSTRAINT; Schema: \w+$/, '')
end
end

def clean_inherited_tables
inherited_tables_regexp = /-- Name: ([\w\.]+); Type: TABLE\n\n[^;]+?INHERITS \([\w\.]+\);/m
inherited_tables_regexp = /-- Name: ([\w\.]+); Type: TABLE; Schema: \w+\n\n[^;]+?INHERITS \([\w\.]+\);/m
inherited_tables = dump.scan(inherited_tables_regexp).map(&:first)
dump.gsub!(inherited_tables_regexp, '')
inherited_tables.each do |inherited_table|
dump.gsub!(/ALTER TABLE ONLY ([\w_]+\.)?#{inherited_table}[^;]+;/, '')

index_regexp = /CREATE INDEX ([\w_]+) ON ([\w_]+\.)?#{inherited_table}[^;]+;/m
dump.scan(index_regexp).map(&:first).each do |inherited_table_index|
dump.gsub!("-- Name: #{inherited_table_index}; Type: INDEX", '')
dump.gsub!(/-- Name: #{inherited_table_index}; Type: INDEX; Schema: \w+/, '')
end
dump.gsub!(index_regexp, '')
end
end

def clean_ignored_schemas
return if options[:ignore_schemas].nil?
options[:ignore_schemas].each do |schema|
dump.gsub!(/-- Name: ([^;]+); Type: \w+; Schema: #{schema}\n\n(?:(?!(-- Name:|SET default_tablespace)).)*/m, '')
dump.gsub!(/-- Name: #{schema}; Type: SCHEMA; Schema: -\n\n(?:(?!(-- Name:|SET default_tablespace)).)*/m, '')
dump.gsub!(/-- Name: \w+; Type: EXTENSION; Schema: -\n\n\nCREATE EXTENSION IF NOT EXISTS \w+ WITH SCHEMA #{schema};(?:(?!(-- Name:|SET default_tablespace)).)*/m, '')
end
end

def clean_partition_tables
partitioned_tables = []

Expand All @@ -99,7 +110,7 @@ def clean_partition_tables
names = []
partitioned_tables.each { |table| names << table.split('.', 2)[1] }
if names.any?
dump.scan(/CREATE (UNIQUE )?INDEX ([\w_]+) ON ([\w_]+\.)?(#{names.join('|')})[^;]+;/m).each { |m| names << m[1] }
dump.scan(/CREATE (UNIQUE )?INDEX (\w+) ON (\w+\.)?(#{names.join('|')})[^;]+;/m).each { |m| names << m[1] }
end
statements.reject! { |stmt| names.any? { |name| stmt.include?(name) } }
@dump = statements.join("\n\n")
Expand All @@ -126,7 +137,7 @@ def clean_options
.transform_values(&:join)

dump.gsub!(/^CREATE( UNIQUE)? INDEX \w+ ON .+\n+/, '')
dump.gsub!(/^-- Name: \w+; Type: INDEX\n+/, '')
dump.gsub!(/^-- Name: \w+; Type: INDEX; Schema: \w+\n+/, '')
indexes.each do |table, indexes_for_table|
dump.gsub!(/^(CREATE TABLE #{table}\b(:?[^;\n]*\n)+\);*\n(?:.*);*)/) { $1 + "\n\n" + indexes_for_table }
end
Expand All @@ -140,6 +151,11 @@ def clean_options
end
end

def clean_schema_comments
# Remove schema in comments for backwards compatibility
dump.gsub!(/^-- (.*); Schema: [\w-]+/, '-- \1')
end

def order_column_definitions(source)
result = []

Expand Down
5 changes: 5 additions & 0 deletions test/clean_dump_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ def test_partitions
assert_cleans_dump "data/partitions.sql", "expectations/partitions.sql"
end

def test_ignored_schemas
assert_cleans_dump "data/ignored_schemas.sql", "expectations/ignored_schemas_pganalyze.sql", ignore_schemas: ['pganalyze']
assert_cleans_dump "data/ignored_schemas.sql", "expectations/ignored_schemas_myschema.sql", ignore_schemas: ['myschema']
end

private

def assert_cleans_dump(input, output, props = {})
Expand Down
Loading
Loading