activerecord-pg-format-db-structure 0.1.1 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0f52ec941c9e147d32ce581a4e5384263455ca48295539f0d3a2b518cc7e4e51
4
- data.tar.gz: 1ab211061fe2fca72d364dc8b92636e01c294ad4efddbd684a1a2b1b072d02a8
3
+ metadata.gz: 9eadcc90f7e5d8ec76f9f9494e7049646bf68ed37df502df31a1dc9fae87d2b6
4
+ data.tar.gz: bee026074f768393231546155fc52e0d00098cbdec981729a63c5a8d1efeb1c4
5
5
  SHA512:
6
- metadata.gz: 87322b447a211cce08c5beebf137ca7a5da4947f0a01f37192978ea6a873d6f990201450ae3764501cccaa04667089b595bce39829d544e417ee7a9426d8ca5d
7
- data.tar.gz: 27ebd693ed145add5112b35805c94e06b4f6f32e03419ffc92c62187116e3ec93d02694b0c67abf153e5a8582643989c2831e74b00f002b5758ba3fc7f6f7c5f
6
+ metadata.gz: efe9804695f586ea988faa923d5db83483b0a0e1395bdaaaabd3dcdbd93358d96a7c5a0f7688b5bf1512d4e14d49bf68f46c65000c9700cb3ad8ef7d63094908
7
+ data.tar.gz: dbdfa7873bd2551f2c1284befbd039c194cc87aaafea7690df8daabc84724c78a06ff3f021940204aa80cdef569566b9c81bfe4cc0aa3aa6180cb7a660e0bb21
data/.rubocop.yml CHANGED
@@ -15,19 +15,10 @@ Style/StringLiteralsInInterpolation:
15
15
  Naming/FileName:
16
16
  Enabled: false
17
17
 
18
- Metrics/BlockLength:
18
+ Naming/VariableNumber:
19
19
  Enabled: false
20
20
 
21
- Metrics/MethodLength:
22
- Enabled: false
23
-
24
- Metrics/AbcSize:
25
- Enabled: false
26
-
27
- Metrics/ClassLength:
28
- Enabled: false
29
-
30
- Metrics/CyclomaticComplexity:
21
+ Metrics:
31
22
  Enabled: false
32
23
 
33
24
  RSpec/SpecFilePathFormat:
data/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.1.3] - 2025-02-02
4
+
5
+ - Rework SQL formatting by only adding indentation to deparsed statements
6
+
7
+ ## [0.1.2] - 2025-01-30
8
+
9
+ - Get rid of `anbt-sql-formatter` dependency since it breaks queries with type casting
10
+
3
11
  ## [0.1.1] - 2025-01-29
4
12
 
5
13
  - Proper deparsing of all statements
data/README.md CHANGED
@@ -221,7 +221,7 @@ ALTER TABLE ONLY public.comments
221
221
 
222
222
 
223
223
  INSERT INTO schema_migrations (version) VALUES
224
- ('20250124155339')
224
+ ('20250124155339')
225
225
  ;
226
226
  ```
227
227
 
@@ -338,7 +338,7 @@ Should be run after other operations that inline alter statements.
338
338
 
339
339
  Returns an SQL string from raw PgQuery statements.
340
340
 
341
- Relying mostly on `PgQuery.deparse`, but applying some formatting using the [anbt-sql-formatter](https://github.com/sonota88/anbt-sql-formatter) gem on select & insert statements.
341
+ Relying mostly on `PgQuery.deparse`, and does a best effort to add some indentation where possible.
342
342
 
343
343
  ## Development
344
344
 
@@ -1,187 +1,88 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "pg_query"
4
- require "anbt-sql-formatter/formatter"
4
+ require_relative "indenter"
5
5
 
6
6
  module ActiveRecordPgFormatDbStructure
7
7
  # Returns a list of SQL strings from a list of PgQuery::RawStmt.
8
8
  class Deparser
9
9
  attr_reader :source
10
10
 
11
- PRETTY_INDENT_STRING = " "
12
-
13
11
  def initialize(source)
14
12
  @source = source
15
13
  end
16
14
 
17
15
  def deparse_raw_statement(raw_statement)
18
16
  case raw_statement.to_h
17
+ in stmt: { insert_stmt: _ }
18
+ deparse_insert_stmt(raw_statement.stmt.insert_stmt)
19
19
  in stmt: { create_stmt: _ }
20
20
  deparse_create_stmt(raw_statement.stmt.create_stmt)
21
- in stmt: { index_stmt: _ }
22
- deparse_index_stmt(raw_statement.stmt.index_stmt)
23
- in stmt: { alter_table_stmt: _ }
24
- deparse_alter_table_stmt(raw_statement.stmt.alter_table_stmt)
25
- in stmt: { select_stmt: _ }
26
- deparse_query_statement(raw_statement.stmt.select_stmt)
27
- in stmt: { insert_stmt: _ }
28
- deparse_insert_statement(raw_statement.stmt.insert_stmt)
29
- in stmt: { create_table_as_stmt: _ }
30
- deparse_create_table_as_stmt(raw_statement.stmt.create_table_as_stmt)
31
21
  in stmt: { view_stmt: _ }
32
22
  deparse_view_stmt(raw_statement.stmt.view_stmt)
23
+ in stmt: { create_table_as_stmt: _ }
24
+ deparse_create_table_as_stmt(raw_statement.stmt.create_table_as_stmt)
25
+ in stmt: { index_stmt: _ }
26
+ deparse_stmt_compact(raw_statement.stmt.index_stmt)
33
27
  else
34
- "\n#{deparse_stmt(raw_statement.stmt.inner)}"
28
+ deparse_stmt_generic(raw_statement.stmt.inner)
35
29
  end
36
30
  end
37
31
 
38
32
  private
39
33
 
40
- def deparse_stmt(stmt)
41
- "\n#{PgQuery.deparse_stmt(stmt)};"
34
+ def deparse_stmt_generic(stmt)
35
+ generic_str = +"\n\n"
36
+ generic_str << deparse_stmt_and_indent(stmt)
37
+ generic_str << ";"
38
+ generic_str
42
39
  end
43
40
 
44
- def deparse_query_statement(stmt)
45
- generic_query_str = +"\n\n"
46
- generic_query_str << pretty_formt_sql_string(PgQuery.deparse_stmt(stmt))
47
- generic_query_str << ";"
41
+ def deparse_stmt_compact(stmt)
42
+ compact_str = +"\n"
43
+ compact_str << deparse_stmt(stmt)
44
+ compact_str << ";"
45
+ compact_str
48
46
  end
49
47
 
50
- def deparse_index_stmt(index_stmt)
51
- deparse_stmt(index_stmt)
48
+ def deparse_insert_stmt(stmt)
49
+ insert_str = +"\n\n\n"
50
+ insert_str << deparse_stmt_and_indent(stmt)
51
+ insert_str << "\n;"
52
+ insert_str
52
53
  end
53
54
 
54
- def deparse_alter_table_stmt(alter_table_stmt)
55
- alter_table_str = +"\n\n"
56
- alter_table_str << PgQuery.deparse_stmt(
57
- PgQuery::AlterTableStmt.new(
58
- **alter_table_stmt.to_h,
59
- cmds: []
60
- )
61
- ).chomp(" ")
62
-
63
- alter_table_cmds_str = alter_table_stmt.cmds.map do |cmd|
64
- "\n #{deparse_alter_table_cmd(cmd)}"
65
- end.join(",")
66
-
67
- alter_table_str << alter_table_cmds_str
68
- alter_table_str << ";"
69
- alter_table_str
70
- end
71
-
72
- def deparse_alter_table_cmd(cmd)
73
- PgQuery.deparse_stmt(
74
- PgQuery::AlterTableStmt.new(
75
- relation: { relname: "tmp" },
76
- cmds: [cmd]
77
- )
78
- ).gsub(/\AALTER ONLY tmp /, "")
79
- end
80
-
81
- def deparse_create_stmt(create_stmt)
82
- placeholder_column = PgQuery::Node.from(
83
- PgQuery::ColumnDef.new(
84
- colname: "placeholder_column",
85
- type_name: {
86
- names: [PgQuery::Node.from_string("placeholder_type")]
87
- }
88
- )
89
- )
90
-
91
- table_str = "\n\n\n-- Name: #{create_stmt.relation.relname}; Type: TABLE;\n\n"
92
- table_str << PgQuery.deparse_stmt(
93
- PgQuery::CreateStmt.new(
94
- **create_stmt.to_h,
95
- table_elts: [placeholder_column]
96
- )
97
- )
55
+ def deparse_create_stmt(stmt)
56
+ table_str = "\n\n\n-- Name: #{stmt.relation.relname}; Type: TABLE;\n\n"
57
+ table_str << deparse_stmt_and_indent(stmt)
98
58
  table_str << ";"
99
-
100
- table_columns = create_stmt.table_elts.map do |elt|
101
- "\n #{deparse_table_elt(elt)}"
102
- end.join(",")
103
- table_columns << "\n"
104
-
105
- table_str[deparse_table_elt(placeholder_column)] = table_columns
106
-
107
59
  table_str
108
60
  end
109
61
 
110
- def deparse_table_elt(elt)
111
- PgQuery.deparse_stmt(
112
- PgQuery::CreateStmt.new(
113
- relation: { relname: "tmp" }, table_elts: [elt]
114
- )
115
- ).gsub(/\ACREATE TABLE ONLY tmp \((.*)\)\z/, '\1')
116
- end
117
-
118
- def deparse_create_table_as_stmt(stmt)
119
- create_table_as_stmt_str = +"\n\n"
120
- create_table_as_stmt_str << PgQuery.deparse_stmt(
121
- PgQuery::CreateTableAsStmt.new(
122
- **stmt.to_h,
123
- query: PgQuery::Node.from(placeholder_query_stmt)
124
- )
125
- )
126
- create_table_as_stmt_str << ";"
127
-
128
- query_str = +"(\n"
129
- query_str << pretty_formt_sql_string(PgQuery.deparse_stmt(stmt.query.inner)).gsub(/^/, PRETTY_INDENT_STRING)
130
- query_str << "\n)"
131
-
132
- create_table_as_stmt_str[placeholder_query_string] = query_str
133
- create_table_as_stmt_str
134
- end
135
-
136
62
  def deparse_view_stmt(stmt)
137
- view_stmt_str = +"\n\n"
138
- view_stmt_str << PgQuery.deparse_stmt(
139
- PgQuery::ViewStmt.new(
140
- **stmt.to_h,
141
- query: PgQuery::Node.from(placeholder_query_stmt)
142
- )
143
- )
144
- view_stmt_str << ";"
145
-
146
- query_str = +"(\n"
147
- query_str << pretty_formt_sql_string(PgQuery.deparse_stmt(stmt.query.inner)).gsub(/^/, PRETTY_INDENT_STRING)
148
- query_str << "\n)"
149
-
150
- view_stmt_str[placeholder_query_string] = query_str
151
- view_stmt_str
63
+ table_str = "\n\n\n-- Name: #{stmt.view.relname}; Type: VIEW;\n\n"
64
+ table_str << deparse_stmt_and_indent(stmt)
65
+ table_str << ";"
66
+ table_str
152
67
  end
153
68
 
154
- def deparse_insert_statement(insert_stmt)
155
- insert_stmt_str = +"\n\n\n"
156
- insert_stmt_str << PgQuery.deparse_stmt(
157
- PgQuery::InsertStmt.new(
158
- **insert_stmt.to_h,
159
- select_stmt: PgQuery::Node.from(placeholder_query_stmt)
160
- )
161
- )
162
- insert_stmt_str << "\n;"
69
+ def deparse_create_table_as_stmt(stmt)
70
+ table_str = "\n\n\n-- Name: #{stmt.into.rel.relname}; Type: MATERIALIZED VIEW;\n\n"
71
+ table_str << deparse_stmt_and_indent(stmt)
163
72
 
164
- query_str = pretty_formt_sql_string(PgQuery.deparse_stmt(insert_stmt.select_stmt.inner))
165
- query_str.gsub!(/\AVALUES /, "VALUES\n ")
73
+ # couldn't find a better solution for this, but probably an OK workaround?
74
+ table_str.gsub!(/ WITH NO DATA\z/, "\nWITH NO DATA")
166
75
 
167
- insert_stmt_str[placeholder_query_string] = query_str
168
- insert_stmt_str
169
- end
170
-
171
- def pretty_formt_sql_string(sql)
172
- rule = AnbtSql::Rule.new
173
- rule.keyword = AnbtSql::Rule::KEYWORD_UPPER_CASE
174
- rule.indent_string = PRETTY_INDENT_STRING
175
- formatter = AnbtSql::Formatter.new(rule)
176
- formatter.format(sql)
76
+ table_str << ";"
77
+ table_str
177
78
  end
178
79
 
179
- def placeholder_query_string
180
- @placeholder_query_string ||= PgQuery.deparse_stmt(placeholder_query_stmt)
80
+ def deparse_stmt_and_indent(stmt)
81
+ Indenter.new(deparse_stmt(stmt)).indent
181
82
  end
182
83
 
183
- def placeholder_query_stmt
184
- @placeholder_query_stmt ||= PgQuery.parse("SELECT placeholder").tree.stmts.first.stmt.select_stmt
84
+ def deparse_stmt(stmt)
85
+ PgQuery.deparse_stmt(stmt)
185
86
  end
186
87
  end
187
88
  end
@@ -0,0 +1,278 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "pg_query"
4
+
5
+ module ActiveRecordPgFormatDbStructure
6
+ # Inserts newlines and whitespace on a deparsed SQL string
7
+ class Indenter
8
+ Token = Data.define(:type, :string)
9
+
10
+ # Reserved Keywords
11
+ ADD = :ADD_P
12
+ ALTER = :ALTER
13
+ AND = :AND
14
+ AS = :AS
15
+ CASE = :CASE
16
+ CREATE = :CREATE
17
+ CROSS = :CROSS
18
+ DROP = :DROP
19
+ ELSE = :ELSE
20
+ END_P = :END_P
21
+ EXCEPT = :EXCEPT
22
+ FETCH = :FETCH
23
+ FOR = :FOR
24
+ FROM = :FROM
25
+ GROUP = :GROUP_P
26
+ HAVING = :HAVING
27
+ INNER = :INNER
28
+ INSERT = :INSERT
29
+ INTERSECT = :INTERSECT
30
+ JOIN = :JOIN
31
+ LEFT = :LEFT
32
+ LIMIT = :LIMIT
33
+ OFFSET = :OFFSET
34
+ OR = :OR
35
+ ORDER = :ORDER
36
+ RIGHT = :RIGHT
37
+ SELECT = :SELECT
38
+ TABLE = :TABLE
39
+ THEN = :THEN
40
+ UNION = :UNION
41
+ VALUES = :VALUES
42
+ VIEW = :VIEW
43
+ WHEN = :WHEN
44
+ WHERE = :WHERE
45
+ WHITESPACE = :WHITESPACE
46
+ WINDOW = :WINDOW
47
+ WITH = :WITH
48
+
49
+ # ASCII tokens
50
+ COMMA = :ASCII_44
51
+ OPEN_PARENS = :ASCII_40
52
+ CLOSE_PARENS = :ASCII_41
53
+
54
+ # Helpers
55
+ PARENS = :PARENS
56
+ INDENT_STRING = " "
57
+ SELECT_PADDING = " "
58
+ TABLE_ELTS = :TABLE_ELTS
59
+
60
+ attr_reader :source
61
+
62
+ def initialize(source)
63
+ @source = PgQuery.deparse(PgQuery.parse(source).tree)
64
+ end
65
+
66
+ def indent
67
+ output = Output.new
68
+ prev_token = nil
69
+ tokens.each do |token|
70
+ output.current_token = token
71
+ case { current_token: token.type, prev_token: prev_token&.type, inside: output.current_scope_type }
72
+ in { current_token: CREATE, inside: nil }
73
+ output.append_scope(type: CREATE)
74
+ output.append_token
75
+ in { current_token: ALTER, inside: nil }
76
+ output.append_scope(type: ALTER, indent: 1)
77
+ output.append_token
78
+ in { current_token: INSERT, inside: nil }
79
+ output.append_scope(type: INSERT, indent: 0)
80
+ output.append_token
81
+ in { current_token: VIEW, inside: CREATE }
82
+ output.append_scope(type: VIEW, indent: 2)
83
+ output.append_token
84
+ in { current_token: WITH, inside: CREATE | VIEW | nil }
85
+ output.append_scope(type: WITH)
86
+ output.append_token
87
+ in { current_token: WHITESPACE, prev_token: AS, inside: VIEW }
88
+ output.append_token
89
+ output.newline
90
+ output.apply_indent
91
+ in { current_token: WHITESPACE, prev_token: COMMA, inside: WITH | SELECT | TABLE_ELTS }
92
+ output.append_token
93
+ output.newline
94
+ output.apply_indent
95
+ in { current_token: COMMA, inside: INSERT }
96
+ output.newline
97
+ output.apply_indent
98
+ output.append_token
99
+ in { current_token: SELECT, inside: WITH | INSERT }
100
+ output.pop_scope
101
+ output.newline
102
+ output.apply_indent
103
+ output.append_token
104
+ output.append_scope(type: SELECT, indent: 2, padding: SELECT_PADDING)
105
+ in { current_token: SELECT }
106
+ output.append_token
107
+ output.append_scope(type: SELECT, indent: 2, padding: SELECT_PADDING)
108
+ in { current_token: ALTER | ADD | DROP, inside: ALTER }
109
+ output.newline
110
+ output.apply_indent
111
+ output.append_token
112
+ in {
113
+ current_token: CROSS | INNER | LEFT | RIGHT | JOIN => type,
114
+ inside: SELECT | FROM | JOIN
115
+ }
116
+ output.pop_scope
117
+ output.newline
118
+ output.apply_indent
119
+ output.append_token
120
+ output.append_scope(type:, indent: 0)
121
+ in {
122
+ current_token: CROSS | INNER | LEFT | RIGHT | JOIN => type,
123
+ inside: CROSS | INNER | LEFT | RIGHT
124
+ }
125
+ output.append_token
126
+ output.pop_scope
127
+ output.append_scope(type:, indent: 0)
128
+ in {
129
+ current_token: FROM | WHERE | GROUP | ORDER | WINDOW | HAVING | LIMIT | OFFSET | FETCH | FOR | UNION |
130
+ INTERSECT | EXCEPT => token_type
131
+ }
132
+ output.pop_scope
133
+ output.newline
134
+ output.apply_indent
135
+ output.append_token
136
+ output.append_scope(type: token_type, indent: 1)
137
+ in { current_token: OR | AND, inside: WHERE }
138
+ output.newline
139
+ output.apply_indent
140
+ output.append_token(rjust: 3)
141
+ in { current_token: CASE }
142
+ output.append_token
143
+ output.append_scope(type: CASE, indent: 1, padding: output.current_padding)
144
+ in { current_token: WHEN | ELSE, inside: CASE }
145
+ output.newline
146
+ output.apply_indent
147
+ output.append_token
148
+ in { current_token: END_P }
149
+ output.pop_scope
150
+ output.newline
151
+ output.apply_indent
152
+ output.append_token
153
+ in { current_token: VALUES, inside: INSERT }
154
+ output.append_token
155
+ output.newline
156
+ output.append_whitespace
157
+ in { current_token: OPEN_PARENS, inside: CREATE }
158
+ output.append_token
159
+ output.newline
160
+ output.append_scope(type: TABLE_ELTS, indent: 2)
161
+ output.apply_indent
162
+ in { current_token: OPEN_PARENS, inside: WITH }
163
+ output.append_token
164
+ output.newline
165
+ output.append_scope(type: PARENS, indent: 2)
166
+ output.apply_indent
167
+ in { current_token: OPEN_PARENS, inside: JOIN }
168
+ output.append_token
169
+ output.newline
170
+ output.append_scope(type: PARENS, indent: 2)
171
+ output.apply_indent
172
+ in { current_token: OPEN_PARENS }
173
+ output.append_scope(type: PARENS)
174
+ output.append_token
175
+ in { current_token: CLOSE_PARENS, inside: TABLE_ELTS }
176
+ output.pop_scope
177
+ output.newline
178
+ output.apply_indent
179
+ output.append_token
180
+ in { current_token: CLOSE_PARENS, inside: PARENS }
181
+ output.pop_scope
182
+ output.append_token
183
+ in { current_token: CLOSE_PARENS }
184
+ loop do
185
+ break if output.pop_scope in PARENS | nil
186
+ end
187
+ output.newline
188
+ output.apply_indent
189
+ output.append_token
190
+ else
191
+ output.append_token
192
+ end
193
+ prev_token = token
194
+ end
195
+ output.to_s
196
+ end
197
+
198
+ private
199
+
200
+ def tokens
201
+ tmp_tokens = []
202
+ prev_token = Data.define(:end).new(0)
203
+ PgQuery.scan(source).first.tokens.each do |token|
204
+ if prev_token.end != token.start
205
+ tmp_tokens << Token.new(
206
+ type: WHITESPACE,
207
+ string: " "
208
+ )
209
+ end
210
+ prev_token = token
211
+ tmp_tokens << Token.new(
212
+ type: token.token,
213
+ string: source[token.start...token.end]
214
+ )
215
+ end
216
+ tmp_tokens
217
+ end
218
+
219
+ # Wrapper that ensures we only append whitespace, and always
220
+ # append the current token exactly once for each loop.
221
+ class Output
222
+ Scope = Data.define(:type, :indent, :padding)
223
+
224
+ def initialize
225
+ @string = +""
226
+ @scopes = [Scope.new(type: nil, indent: 0, padding: "")]
227
+ @current_token = nil
228
+ end
229
+
230
+ def to_s
231
+ # clean extra whitespace at end of string
232
+ @string.gsub(/\s+\n/, "\n").freeze
233
+ end
234
+
235
+ def current_scope_type
236
+ @scopes.last.type
237
+ end
238
+
239
+ def current_token=(token)
240
+ raise "Previous token was not appended!" unless @current_token.nil?
241
+
242
+ @current_token = token
243
+ end
244
+
245
+ def append_scope(type:, indent: 0, padding: "")
246
+ @scopes << Scope.new(type:, indent:, padding:)
247
+ end
248
+
249
+ def current_padding
250
+ @scopes.last.padding
251
+ end
252
+
253
+ def pop_scope
254
+ @scopes.pop.type
255
+ end
256
+
257
+ def newline
258
+ @string << "\n"
259
+ end
260
+
261
+ def append_whitespace
262
+ @string << " "
263
+ end
264
+
265
+ def apply_indent
266
+ @string << (INDENT_STRING * @scopes.sum(&:indent))
267
+ @string << @scopes.last.padding
268
+ end
269
+
270
+ def append_token(rjust: 0)
271
+ raise "Token was already appended!" if @current_token.nil?
272
+
273
+ @string << @current_token.string.rjust(rjust)
274
+ @current_token = nil
275
+ end
276
+ end
277
+ end
278
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActiveRecordPgFormatDbStructure
4
- VERSION = "0.1.1"
4
+ VERSION = "0.1.3"
5
5
  end
metadata CHANGED
@@ -1,28 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activerecord-pg-format-db-structure
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jell
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2025-01-29 00:00:00.000000000 Z
10
+ date: 2025-02-02 00:00:00.000000000 Z
11
11
  dependencies:
12
- - !ruby/object:Gem::Dependency
13
- name: anbt-sql-formatter
14
- requirement: !ruby/object:Gem::Requirement
15
- requirements:
16
- - - "~>"
17
- - !ruby/object:Gem::Version
18
- version: '0.1'
19
- type: :runtime
20
- prerelease: false
21
- version_requirements: !ruby/object:Gem::Requirement
22
- requirements:
23
- - - "~>"
24
- - !ruby/object:Gem::Version
25
- version: '0.1'
26
12
  - !ruby/object:Gem::Dependency
27
13
  name: pg_query
28
14
  requirement: !ruby/object:Gem::Requirement
@@ -55,6 +41,7 @@ files:
55
41
  - lib/activerecord-pg-format-db-structure.rb
56
42
  - lib/activerecord-pg-format-db-structure/deparser.rb
57
43
  - lib/activerecord-pg-format-db-structure/formatter.rb
44
+ - lib/activerecord-pg-format-db-structure/indenter.rb
58
45
  - lib/activerecord-pg-format-db-structure/preprocessors/remove_whitespaces.rb
59
46
  - lib/activerecord-pg-format-db-structure/railtie.rb
60
47
  - lib/activerecord-pg-format-db-structure/tasks/clean_db_structure.rake