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
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
## [Unreleased]

- Add preprocessors config that allows applying text transforms to the input before parsing
- Add preprocessor to remove `\restrict` and `\unrestrict` pragmas that appeared in newer versions of pg_dump

## [0.5.0] - 2025-08-04

- Upgrade pg_query to 6.1 to add support for latest mac OS version
Expand Down
16 changes: 15 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Say good-bye to those pesky diffs you get between coworkers!

By default, it will:

* remove `\restrict` and `\unrestrict` pragmas
* Inline primary key declarations
* Inline SERIAL type declarations
* Inline table constraints
Expand All @@ -27,6 +28,8 @@ As an example, the task will transform this raw `structure.sql`:
<summary>Click to expand</summary>

```sql
\restrict 1234

--
-- Name: pgcrypto; Type: EXTENSION; Schema: -; Owner: -
--
Expand Down Expand Up @@ -261,6 +264,10 @@ If you want to configure which transforms to use, you can configure the library

```ruby
Rails.application.configure do
config.activerecord_pg_format_db_structure.preprocessors = [
Preprocessors::RemoveRestrictPragmas
]

config.activerecord_pg_format_db_structure.transforms = [
ActiveRecordPgFormatDbStructure::Transforms::RemoveCommentsOnExtensions,
ActiveRecordPgFormatDbStructure::Transforms::RemoveDefaultsSetCommands,
Expand All @@ -271,7 +278,7 @@ Rails.application.configure do
ActiveRecordPgFormatDbStructure::Transforms::InlineConstraints,
ActiveRecordPgFormatDbStructure::Transforms::MoveIndicesAfterCreateTable,
ActiveRecordPgFormatDbStructure::Transforms::GroupAlterTableStatements,
ActiveRecordPgFormatDbStructure::Transforms::SortTableColumns,
ActiveRecordPgFormatDbStructure::Transforms::SortTableColumns
]

config.activerecord_pg_format_db_structure.deparser = ActiveRecordPgFormatDbStructure::Deparser
Expand All @@ -287,6 +294,13 @@ structure = File.read("db/structure.sql")
formatted = ActiveRecordPgFormatDbStructure::Formatter.new.format(structure)
File.write("db/structure.sql", formatted)
```
## Preprocessors

### RemoveRestrictPragmas

Remove `\restrict` and `\unrestrict` pragmas that were added in newer
versions of `pg_dump`, since they are not valid SQL syntax and
therefore prevent parsing the file as SQL.

## Transformers

Expand Down
5 changes: 5 additions & 0 deletions lib/activerecord-pg-format-db-structure.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

require_relative "activerecord-pg-format-db-structure/deparser"
require_relative "activerecord-pg-format-db-structure/statement_appender"
require_relative "activerecord-pg-format-db-structure/preprocessors/remove_restrict_pragmas"
require_relative "activerecord-pg-format-db-structure/transforms/remove_comments_on_extensions"
require_relative "activerecord-pg-format-db-structure/transforms/inline_serials"
require_relative "activerecord-pg-format-db-structure/transforms/inline_primary_keys"
Expand All @@ -16,6 +17,10 @@
require_relative "activerecord-pg-format-db-structure/transforms/sort_table_columns"

module ActiveRecordPgFormatDbStructure
DEFAULT_PREPROCESSORS = [
Preprocessors::RemoveRestrictPragmas
].freeze

DEFAULT_TRANSFORMS = [
Transforms::RemoveCommentsOnExtensions,
Transforms::RemoveDefaultsSetCommands,
Expand Down
8 changes: 7 additions & 1 deletion lib/activerecord-pg-format-db-structure/formatter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,25 @@
module ActiveRecordPgFormatDbStructure
# Formats & normalizes in place the given SQL string
class Formatter
attr_reader :transforms, :deparser, :statement_appender
attr_reader :preprocessors, :transforms, :deparser, :statement_appender

def initialize(
preprocessors: DEFAULT_PREPROCESSORS,
transforms: DEFAULT_TRANSFORMS,
deparser: DEFAULT_DEPARSER,
statement_appender: DEFAULT_STATEMENT_APPENDER
)
@preprocessors = preprocessors
@transforms = transforms
@deparser = deparser
@statement_appender = statement_appender
end

def format(source)
preprocessors.each do |preprocessor|
preprocessor.new(source).preprocess!
end

raw_statements = PgQuery.parse(source).tree.stmts

transforms.each do |transform|
Expand Down
16 changes: 16 additions & 0 deletions lib/activerecord-pg-format-db-structure/preprocessors/base.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# frozen_string_literal: true

require "pg_query"

module ActiveRecordPgFormatDbStructure
module Preprocessors
# :nodoc:
class Base
attr_reader :source

def initialize(source)
@source = source
end
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# frozen_string_literal: true

require_relative "base"

module ActiveRecordPgFormatDbStructure
module Preprocessors
# Inline non-foreign key constraints into table declaration
class RemoveRestrictPragmas < Base
def preprocess!
source.gsub!(/^(\\restrict .*)$/, "")
source.gsub!(/^(\\unrestrict .*)$/, "")
end
end
end
end
1 change: 1 addition & 0 deletions lib/activerecord-pg-format-db-structure/railtie.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ module ActiveRecordPgFormatDbStructure
# Setup for Rails
class Railtie < Rails::Railtie
config.activerecord_pg_format_db_structure = ActiveSupport::OrderedOptions.new
config.activerecord_pg_format_db_structure.preprocessors = DEFAULT_PREPROCESSORS.dup
config.activerecord_pg_format_db_structure.transforms = DEFAULT_TRANSFORMS.dup
config.activerecord_pg_format_db_structure.deparser = DEFAULT_DEPARSER
config.activerecord_pg_format_db_structure.statement_appender = DEFAULT_STATEMENT_APPENDER
Expand Down
34 changes: 34 additions & 0 deletions spec/activerecord-pg-format-db-structure/formatter_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -229,5 +229,39 @@
;
SQL
end

it "handles pg_dump's \restrict commands" do
formatter = described_class.new

source = +<<~SQL
\\restrict 1234

--
-- Name: comments; Type: TABLE; Schema: public; Owner: -
--

CREATE TABLE public.comments (
id bigserial PRIMARY KEY,
user_id bigint NOT NULL,
post_id bigint NOT NULL,
created_at timestamp(6) without time zone NOT NULL,
updated_at timestamp(6) without time zone NOT NULL
);

\\unrestrict 1234
SQL

expect(formatter.format(source)).to eq(<<~SQL)
-- Name: comments; Type: TABLE;

CREATE TABLE public.comments (
id bigserial PRIMARY KEY,
post_id bigint NOT NULL,
user_id bigint NOT NULL,
created_at timestamp(6) NOT NULL,
updated_at timestamp(6) NOT NULL
);
SQL
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# frozen_string_literal: true

RSpec.describe ActiveRecordPgFormatDbStructure::Preprocessors::RemoveRestrictPragmas do
describe "#preprocess!" do
it 'removes \restrict and \unrestrict pragmas' do
source = +<<~SQL
\\restrict 1234

CREATE TABLE public.comments (
id bigint NOT NULL,
user_id bigint NOT NULL,
post_id bigint NOT NULL,
created_at timestamp(6) without time zone NOT NULL,
updated_at timestamp(6) without time zone NOT NULL
);

\\unrestrict 1234
SQL

described_class.new(
source
).preprocess!

expect(source).to eq(<<~SQL)


CREATE TABLE public.comments (
id bigint NOT NULL,
user_id bigint NOT NULL,
post_id bigint NOT NULL,
created_at timestamp(6) without time zone NOT NULL,
updated_at timestamp(6) without time zone NOT NULL
);


SQL
end
end
end