niceql 0.1.25 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3b460b8c53129e07c90a14ebf63de07534d07bda56e8b563df2570659d597163
4
- data.tar.gz: 63c4c608e1ae3c087ff4f3e8099a6ad3f3352a13498cfd9d54ca551fd8284c0b
3
+ metadata.gz: 2056d114407ed81b47224f1bc0f60d2e65bb88118667f074fd972149203bd6ea
4
+ data.tar.gz: 48c228ee2240a0fd8beec6ecc1c312b42197a8a259bf1d5b438e41fd55c51680
5
5
  SHA512:
6
- metadata.gz: c71dc21142f026ce021836437215fe92b87451b64c58cf1b9c6aa492e5c8a1e2186b97f6e1e9f114cf074cdae9f36d3e381863eebd5dd7e5e4a88c4483299056
7
- data.tar.gz: 60986d42e844edcda1f6a66b83d3edc1b311078a463c15d321ea3e9218f33252764bb2391a7f598fbcbffc6e9cc4af97c6862a072b4b357ff11afd14680830e1
6
+ metadata.gz: 070a9574f50f434136474dfc1b671956b8df3529434f2e13f36e4b4c952a1dbc23da5a9e81a5d8eba082154c523c6056476b25396ec52654dcbe0436ae04c18e
7
+ data.tar.gz: e8b550669250d612233b7fdbced172d12cd6d348dd8bfda21ff6ff8dda0358c6cf59e23aa917bbade0f49286017173a10099488a830d1e0802efd71faa98b35a
data/CHANGELOG.md CHANGED
@@ -1,3 +1,25 @@
1
+ # 0.4.0
2
+ * merged PR https://github.com/alekseyl/niceql/pull/19, now Arel is also extended with niceql methods!!
3
+ * test and better niceql comparisons assertion
4
+ * tests were trialed against rails 4.2 and some additional conditions were added for later cases
5
+
6
+ # 0.3.0
7
+ * ruby forced to >= 2.4
8
+ * String match extension no longer needed
9
+ * fixed issue with missing HINT and DETAIL string ( https://github.com/alekseyl/niceql/issues/18 )
10
+ * both new and old activerecord StatementInvalid formats supported
11
+ * major prettify_pg_err refactoring ( much cleaner code now )
12
+
13
+ # 0.2.0
14
+ * Fix to issue https://github.com/alekseyl/niceql/pull/17#issuecomment-924278172. ActiveRecord base config is no longer a hash,
15
+ so it does not have dig method, hence it's breaking the ar_using_pg_adapter? method.
16
+ * active_record added as development dependency :( for proper testing cover.
17
+
18
+ # 0.1.30
19
+ * ActiveRecord pg check for config now will try both connection_db_config and connection_config for adapter verification
20
+ * prettify_pg_errors will not be set to true if ActiveRecord adapter is not using pg, i.e. ar_using_pg_adapter? is false.
21
+ * rake dev dependency bumped according to security issues
22
+
1
23
  # 0.1.24/25
2
24
 
3
25
  * No features, just strict ruby dependency for >= 2.3,
data/README.md CHANGED
@@ -1,10 +1,13 @@
1
1
  # Niceql
2
2
 
3
- This is a small, nice, simple and dependentless solution for SQL prettifiyng for Ruby.
3
+ This is a small, nice, simple and zero dependency solution for SQL prettifying for Ruby.
4
4
  It can be used in an irb console without any dependencies ( run bin/console and look for examples ).
5
5
 
6
- Any reasonable suggestions on formatting/coloring are welcome
6
+ Any reasonable suggestions are welcome.
7
7
 
8
+ **Please pay attention: untill issue https://github.com/alekseyl/niceql/issues/16 is resolved any UPDATE or INSERT request might corrupt your data, don't use on production!**
9
+
10
+
8
11
  ## Before/After
9
12
  ### SQL prettifier:
10
13
  ![alt text](https://github.com/alekseyl/niceql/raw/master/to_niceql.png "To_niceql")
@@ -41,9 +44,11 @@ Or install it yourself as:
41
44
  ```ruby
42
45
  Niceql.configure do |c|
43
46
  # Setting pg_adapter_with_nicesql to true will force formatting SQL queries
44
- # before executing them, this will lead to better SQL-query debugging and much more clearer error messages
47
+ # before execution. Formatted SQL will lead to much better SQL-query debugging and much more clearer error messages
45
48
  # if you are using Postgresql as a data source.
46
- # You can adjust pg_adapter in prooduction but do it at your own risk!
49
+ #
50
+ # You can adjust pg_adapter in production but do it at your own risk!
51
+ #
47
52
  # If you need to debug SQL queries in production use exec_niceql
48
53
  # default: false
49
54
  # uncomment next string to enable in development
@@ -53,7 +58,7 @@ Niceql.configure do |c|
53
58
  # default: false
54
59
  # c.prettify_active_record_log_output = true
55
60
 
56
- # now error prettifying is configurable
61
+ # Error prettifying is also configurable
57
62
  # default: defined? ::ActiveRecord::Base && ActiveRecord::Base.configurations[Rails.env]['adapter'] == 'postgresql'
58
63
  # c.prettify_pg_errors = defined? ::ActiveRecord::Base && ActiveRecord::Base.configurations[Rails.env]['adapter'] == 'postgresql'
59
64
 
@@ -82,7 +87,7 @@ end
82
87
  ### With ActiveRecord
83
88
 
84
89
  ```ruby
85
- # puts colorized ( or not if you are willing so ) to_niceql ( you need to call puts otherwise to_niceql looks ugly )
90
+ # puts colorized and formatted corresponding SQL query
86
91
  Model.scope.niceql
87
92
 
88
93
  # only formatting without colorization, you can run output of to_niceql as a SQL query in connection.execute
@@ -107,23 +112,23 @@ end
107
112
  #=>
108
113
  #=> SELECT *
109
114
  #=> FROM table
110
-
111
-
112
-
115
+
113
116
 
114
- # rails combines err with query, so don't forget to do it yourself:
115
- puts Niceql::Prettifier.prettify_pg_err( "#{pg_err_output}\n#{sql_query}" )
117
+ puts Niceql::Prettifier.prettify_pg_err( pg_err_output, sql_query )
116
118
 
117
119
  # to get real nice result you should execute prettified version (i.e. execute( prettified_sql ) !) of query on your DB!
118
120
  # otherwise you will not get such a nice output
119
- puts Niceql::Prettifier.prettify_pg_err(<<~ERR )
121
+ raw_sql = <<~SQL
122
+ SELECT err
123
+ FROM ( VALUES(1), (2) )
124
+ ORDER BY 1
125
+ SQL
126
+
127
+ puts Niceql::Prettifier.prettify_pg_err(<<~ERR, raw_sql )
120
128
  ERROR: VALUES in FROM must have an alias
121
129
  LINE 2: FROM ( VALUES(1), (2) )
122
130
  ^
123
131
  HINT: For example, FROM (VALUES ...) [AS] foo.
124
- SELECT err
125
- FROM ( VALUES(1), (2) )
126
- ORDER BY 1
127
132
  ERR
128
133
 
129
134
 
@@ -1,3 +1,3 @@
1
1
  module Niceql
2
- VERSION = "0.1.25"
2
+ VERSION = '0.4.0'
3
3
  end
data/lib/niceql.rb CHANGED
@@ -1,19 +1,18 @@
1
1
  require "niceql/version"
2
- require 'niceql/string'
3
2
 
4
3
  module Niceql
5
4
 
6
5
  module StringColorize
7
6
  def self.colorize_verb( str)
8
- #yellow ANSI color
7
+ # yellow ANSI color
9
8
  "\e[0;33;49m#{str}\e[0m"
10
9
  end
11
10
  def self.colorize_str(str)
12
- #cyan ANSI color
11
+ # cyan ANSI color
13
12
  "\e[0;36;49m#{str}\e[0m"
14
13
  end
15
14
  def self.colorize_err(err)
16
- #red ANSI color
15
+ # red ANSI color
17
16
  "\e[0;31;49m#{err}\e[0m"
18
17
  end
19
18
  end
@@ -45,168 +44,182 @@ module Niceql
45
44
  SQL_COMMENTS_CLEARED = /(\s*?--.+\s{1})|(\s*$\s*\/\*[^\/\*]*\*\/\s{1})/
46
45
  COMMENT_CONTENT = /[\S]+[\s\S]*[\S]+/
47
46
 
48
- def self.config
49
- Niceql.config
50
- end
47
+ class << self
48
+ def config
49
+ Niceql.config
50
+ end
51
51
 
52
+ def prettify_err(err, original_sql_query = nil)
53
+ prettify_pg_err( err.to_s, original_sql_query )
54
+ end
52
55
 
53
- def self.prettify_err(err)
54
- prettify_pg_err( err.to_s )
55
- end
56
56
 
57
+ # Postgres error output:
58
+ # ERROR: VALUES in FROM must have an alias
59
+ # LINE 2: FROM ( VALUES(1), (2) );
60
+ # ^
61
+ # HINT: For example, FROM (VALUES ...) [AS] foo.
57
62
 
58
- # Postgres error output:
59
- # ERROR: VALUES in FROM must have an alias
60
- # LINE 2: FROM ( VALUES(1), (2) );
61
- # ^
62
- # HINT: For example, FROM (VALUES ...) [AS] foo.
63
-
64
- # May go without HINT or DETAIL:
65
- # ERROR: column "usr" does not exist
66
- # LINE 1: SELECT usr FROM users ORDER BY 1
67
- # ^
68
-
69
- # ActiveRecord::StatementInvalid will add original SQL query to the bottom like this:
70
- # ActiveRecord::StatementInvalid: PG::UndefinedColumn: ERROR: column "usr" does not exist
71
- # LINE 1: SELECT usr FROM users ORDER BY 1
72
- # ^
73
- #: SELECT usr FROM users ORDER BY 1
74
-
75
- # prettify_pg_err parses ActiveRecord::StatementInvalid string,
76
- # but you may use it without ActiveRecord either way:
77
- # prettify_pg_err( err + "\n" + sql ) OR prettify_pg_err( err, sql )
78
- # don't mess with original sql query, or prettify_pg_err will deliver incorrect results
79
- def self.prettify_pg_err(err, original_sql_query = nil)
80
- return err if err[/LINE \d+/].nil?
81
- err_line_num = err[/LINE \d+/][5..-1].to_i
82
-
83
- #
84
- start_sql_line = err.lines[3][/(HINT|DETAIL)/] ? 4 : 3
85
- err_body = start_sql_line < err.lines.length ? err.lines[start_sql_line..-1] : original_sql_query&.lines
86
-
87
-
88
- # this means original query is missing so it's nothing to prettify
89
- return err unless err_body
90
-
91
- err_quote = ( err.lines[1][/\.\.\..+\.\.\./] && err.lines[1][/\.\.\..+\.\.\./][3..-4] ) ||
92
- ( err.lines[1][/\.\.\..+/] && err.lines[1][/\.\.\..+/][3..-1] )
93
-
94
- # line[2] is err carret line i.e.: ' ^'
95
- # err.lines[1][/LINE \d+:/].length+1..-1 - is a position from error quote begin
96
- err_carret_line = err.lines[2][err.lines[1][/LINE \d+:/].length+1..-1]
97
- # err line will be painted in red completely, so we just remembering it and use
98
- # to replace after paiting the verbs
99
- err_line = err_body[err_line_num-1]
100
-
101
- # when err line is too long postgres quotes it part in double '...'
102
- if err_quote
103
- err_quote_carret_offset = err_carret_line.length - err.lines[1].index( '...' ) + 3
104
- err_carret_line = ' ' * ( err_line.index( err_quote ) + err_quote_carret_offset ) + "^\n"
105
- end
63
+ # May go without HINT or DETAIL:
64
+ # ERROR: column "usr" does not exist
65
+ # LINE 1: SELECT usr FROM users ORDER BY 1
66
+ # ^
106
67
 
107
- err_carret_line = " " + err_carret_line if err_body[0].start_with?(': ')
108
- # if mistake is on last string than err_line.last != \n so we need to prepend \n to carret line
109
- err_carret_line = "\n" + err_carret_line unless err_line[-1] == "\n"
68
+ # ActiveRecord::StatementInvalid will add original SQL query to the bottom like this:
69
+ # ActiveRecord::StatementInvalid: PG::UndefinedColumn: ERROR: column "usr" does not exist
70
+ # LINE 1: SELECT usr FROM users ORDER BY 1
71
+ # ^
72
+ #: SELECT usr FROM users ORDER BY 1
110
73
 
111
- #colorizing verbs and strings
112
- err_body = err_body.join.gsub(/#{VERBS}/ ) { |verb| StringColorize.colorize_verb(verb) }
113
- .gsub(STRINGS){ |str| StringColorize.colorize_str(str) }
74
+ # prettify_pg_err parses ActiveRecord::StatementInvalid string,
75
+ # but you may use it without ActiveRecord either way:
76
+ # prettify_pg_err( err + "\n" + sql ) OR prettify_pg_err( err, sql )
77
+ # don't mess with original sql query, or prettify_pg_err will deliver incorrect results
78
+ def prettify_pg_err(err, original_sql_query = nil)
79
+ return err if err[/LINE \d+/].nil?
80
+ err_line_num = err[/LINE \d+/][5..-1].to_i
81
+ # LINE 1: SELECT usr FROM users ORDER BY 1
82
+ err_address_line = err.lines[1]
114
83
 
115
- #reassemling error message
116
- err_body = err_body.lines
117
- err_body[err_line_num-1]= StringColorize.colorize_err( err_line )
118
- err_body.insert( err_line_num, StringColorize.colorize_err( err_carret_line ) )
84
+ start_sql_line = 3 if err.lines.length <= 3
85
+ # error not always contains HINT
86
+ start_sql_line ||= err.lines[3][/(HINT|DETAIL)/] ? 4 : 3
87
+ sql_body = start_sql_line < err.lines.length ? err.lines[start_sql_line..-1] : original_sql_query&.lines
119
88
 
120
- err.lines[0..start_sql_line-1].join + err_body.join
121
- end
89
+ # this means original query is missing so it's nothing to prettify
90
+ return err unless sql_body
122
91
 
123
- def self.prettify_sql( sql, colorize = true )
124
- indent = 0
125
- parentness = []
126
-
127
- sql = sql.split( SQL_COMMENTS ).each_slice(2).map{ | sql_part, comment |
128
- # remove additional formatting for sql_parts but leave comment intact
129
- [sql_part.gsub(/[\s]+/, ' '),
130
- # comment.match?(/\A\s*$/) - SQL_COMMENTS gets all comment content + all whitespaced chars around
131
- # so this sql_part.length == 0 || comment.match?(/\A\s*$/) checks does the comment starts from new line
132
- comment && ( sql_part.length == 0 || comment.match?(/\A\s*$/) ? "\n#{comment[COMMENT_CONTENT]}\n" : comment[COMMENT_CONTENT] ) ]
133
- }.flatten.join(' ')
134
-
135
- sql.gsub!(/ \n/, "\n")
136
-
137
- sql.gsub!(STRINGS){ |str| StringColorize.colorize_str(str) } if colorize
138
-
139
- first_verb = true
140
- prev_was_comment = false
141
-
142
- sql.gsub!( /(#{VERBS}|#{BRACKETS}|#{SQL_COMMENTS_CLEARED})/) do |verb|
143
- if 'SELECT' == verb
144
- indent += config.indentation_base if !config.open_bracket_is_newliner || parentness.last.nil? || parentness.last[:nested]
145
- parentness.last[:nested] = true if parentness.last
146
- add_new_line = !first_verb
147
- elsif verb == '('
148
- next_closing_bracket = Regexp.last_match.post_match.index(')')
149
- # check if brackets contains SELECT statement
150
- add_new_line = !!Regexp.last_match.post_match[0..next_closing_bracket][/SELECT/] && config.open_bracket_is_newliner
151
- parentness << { nested: add_new_line }
152
- elsif verb == ')'
153
- # this also covers case when right bracket is used without corresponding left one
154
- add_new_line = parentness.last.nil? || parentness.last[:nested]
155
- indent -= ( parentness.last.nil? ? 2 * config.indentation_base : (parentness.last[:nested] ? config.indentation_base : 0) )
156
- indent = 0 if indent < 0
157
- parentness.pop
158
- elsif verb[POSSIBLE_INLINER]
159
- # in postgres ORDER BY can be used in aggregation function this will keep it
160
- # inline with its agg function
161
- add_new_line = parentness.last.nil? || parentness.last[:nested]
162
- else
163
- add_new_line = verb[/(#{INLINE_VERBS})/].nil?
164
- end
92
+ # err line will be painted in red completely, so we just remembering it and use
93
+ # to replace after painting the verbs
94
+ err_line = sql_body[err_line_num - 1]
165
95
 
166
- # !add_new_line && previous_was_comment means we had newlined comment, and now even
167
- # if verb is inline verb we will need to add new line with indentation BUT all
168
- # inliners match with a space before so we need to strip it
169
- verb.lstrip! if !add_new_line && prev_was_comment
170
96
 
171
- add_new_line = prev_was_comment unless add_new_line
172
- add_indent = !first_verb && add_new_line
97
+ #colorizing verbs and strings
98
+ colorized_sql_body = sql_body.join.gsub(/#{VERBS}/ ) { |verb| StringColorize.colorize_verb(verb) }
99
+ .gsub(STRINGS){ |str| StringColorize.colorize_str(str) }
173
100
 
174
- if verb[SQL_COMMENTS_CLEARED]
175
- verb = verb[COMMENT_CONTENT]
176
- prev_was_comment = true
177
- else
178
- first_verb = false
179
- prev_was_comment = false
101
+ #reassemling error message
102
+ err_body = colorized_sql_body.lines
103
+ # replacing colorized line contained error and adding caret line
104
+ err_body[err_line_num - 1]= StringColorize.colorize_err( err_line )
105
+
106
+ err_caret_line = extract_err_caret_line( err_address_line, err_line, sql_body, err )
107
+ err_body.insert( err_line_num, StringColorize.colorize_err( err_caret_line ) )
108
+
109
+ err.lines[0..start_sql_line-1].join + err_body.join
110
+ end
111
+
112
+ def prettify_sql( sql, colorize = true )
113
+ indent = 0
114
+ parentness = []
115
+
116
+ sql = sql.split( SQL_COMMENTS ).each_slice(2).map{ | sql_part, comment |
117
+ # remove additional formatting for sql_parts but leave comment intact
118
+ [sql_part.gsub(/[\s]+/, ' '),
119
+ # comment.match?(/\A\s*$/) - SQL_COMMENTS gets all comment content + all whitespaced chars around
120
+ # so this sql_part.length == 0 || comment.match?(/\A\s*$/) checks does the comment starts from new line
121
+ comment && ( sql_part.length == 0 || comment.match?(/\A\s*$/) ? "\n#{comment[COMMENT_CONTENT]}\n" : comment[COMMENT_CONTENT] ) ]
122
+ }.flatten.join(' ')
123
+
124
+ sql.gsub!(/ \n/, "\n")
125
+
126
+ sql.gsub!(STRINGS){ |str| StringColorize.colorize_str(str) } if colorize
127
+
128
+ first_verb = true
129
+ prev_was_comment = false
130
+
131
+ sql.gsub!( /(#{VERBS}|#{BRACKETS}|#{SQL_COMMENTS_CLEARED})/) do |verb|
132
+ if 'SELECT' == verb
133
+ indent += config.indentation_base if !config.open_bracket_is_newliner || parentness.last.nil? || parentness.last[:nested]
134
+ parentness.last[:nested] = true if parentness.last
135
+ add_new_line = !first_verb
136
+ elsif verb == '('
137
+ next_closing_bracket = Regexp.last_match.post_match.index(')')
138
+ # check if brackets contains SELECT statement
139
+ add_new_line = !!Regexp.last_match.post_match[0..next_closing_bracket][/SELECT/] && config.open_bracket_is_newliner
140
+ parentness << { nested: add_new_line }
141
+ elsif verb == ')'
142
+ # this also covers case when right bracket is used without corresponding left one
143
+ add_new_line = parentness.last.nil? || parentness.last[:nested]
144
+ indent -= ( parentness.last.nil? ? 2 * config.indentation_base : (parentness.last[:nested] ? config.indentation_base : 0) )
145
+ indent = 0 if indent < 0
146
+ parentness.pop
147
+ elsif verb[POSSIBLE_INLINER]
148
+ # in postgres ORDER BY can be used in aggregation function this will keep it
149
+ # inline with its agg function
150
+ add_new_line = parentness.last.nil? || parentness.last[:nested]
151
+ else
152
+ add_new_line = verb[/(#{INLINE_VERBS})/].nil?
153
+ end
154
+
155
+ # !add_new_line && previous_was_comment means we had newlined comment, and now even
156
+ # if verb is inline verb we will need to add new line with indentation BUT all
157
+ # inliners match with a space before so we need to strip it
158
+ verb.lstrip! if !add_new_line && prev_was_comment
159
+
160
+ add_new_line = prev_was_comment unless add_new_line
161
+ add_indent = !first_verb && add_new_line
162
+
163
+ if verb[SQL_COMMENTS_CLEARED]
164
+ verb = verb[COMMENT_CONTENT]
165
+ prev_was_comment = true
166
+ else
167
+ first_verb = false
168
+ prev_was_comment = false
169
+ end
170
+
171
+ verb = StringColorize.colorize_verb(verb) if !%w[( )].include?(verb) && colorize
172
+
173
+ subs = ( add_indent ? indent_multiline(verb, indent) : verb)
174
+ !first_verb && add_new_line ? "\n" + subs : subs
180
175
  end
181
176
 
182
- verb = StringColorize.colorize_verb(verb) if !['(', ')'].include?(verb) && colorize
177
+ # clear all spaces before newlines, and all whitespaces before strings endings
178
+ sql.tap{ |slf| slf.gsub!( /\s+\n/, "\n" ) }.tap{ |slf| slf.gsub!(/\s+\z/, '') }
179
+ end
183
180
 
184
- subs = ( add_indent ? indent_multiline(verb, indent) : verb)
185
- !first_verb && add_new_line ? "\n" + subs : subs
181
+ def prettify_multiple( sql_multi, colorize = true )
182
+ sql_multi.split( /(?>#{SQL_COMMENTS})|(\;)/ ).inject(['']) { |queries, pattern|
183
+ queries.last << pattern
184
+ queries << '' if pattern == ';'
185
+ queries
186
+ }.map!{ |sql|
187
+ # we were splitting by comments and ;, so if next sql start with comment we've got a misplaced \n\n
188
+ sql.match?(/\A\s+\z/) ? nil : prettify_sql( sql, colorize )
189
+ }.compact.join("\n\n")
186
190
  end
187
191
 
188
- # clear all spaces before newlines, and all whitespaces before string end
189
- sql.tap{ |slf| slf.gsub!( /\s+\n/, "\n" ) }.tap{ |slf| slf.gsub!(/\s+\z/, '') }
190
- end
192
+ private_class_method
193
+ def indent_multiline( verb, indent )
194
+ if verb.match?(/.\s*\n\s*./)
195
+ verb.lines.map!{|ln| ln.prepend(' ' * indent)}.join("\n")
196
+ else
197
+ verb.prepend(' ' * indent)
198
+ end
199
+ end
191
200
 
192
- def self.prettify_multiple( sql_multi, colorize = true )
193
- sql_multi.split( /(?>#{SQL_COMMENTS})|(\;)/ ).inject(['']) { |queries, pattern|
194
- queries.last << pattern
195
- queries << '' if pattern == ';'
196
- queries
197
- }.map!{ |sql|
198
- # we were splitting by comments and ;, so if next sql start with comment we've got a misplaced \n\n
199
- sql.match?(/\A\s+\z/) ? nil : prettify_sql( sql, colorize )
200
- }.compact.join("\n\n")
201
- end
201
+ private_class_method
202
+ def extract_err_caret_line( err_address_line, err_line, sql_body, err )
203
+ # LINE could be quoted ( both sides and sometimes only from one ):
204
+ # "LINE 1: ...t_id\" = $13 AND \"products\".\"carrier_id\" = $14 AND \"product_t...\n",
205
+ err_quote = (err_address_line.match(/\.\.\.(.+)\.\.\./) || err_address_line.match(/\.\.\.(.+)/) ).try(:[], 1)
206
+
207
+ # line[2] is original err caret line i.e.: ' ^'
208
+ # err_address_line[/LINE \d+:/].length+1..-1 - is a position from error quote begin
209
+ err_caret_line = err.lines[2][err_address_line[/LINE \d+:/].length+1..-1]
210
+
211
+ # when err line is too long postgres quotes it in double '...'
212
+ # so we need to reposition caret against original line
213
+ if err_quote
214
+ err_quote_caret_offset = err_caret_line.length - err_address_line.index( '...' ).to_i + 3
215
+ err_caret_line = ' ' * ( err_line.index( err_quote ) + err_quote_caret_offset ) + "^\n"
216
+ end
202
217
 
203
- private
204
- def self.indent_multiline( verb, indent )
205
- #
206
- if verb.match?(/.\s*\n\s*./)
207
- verb.lines.map!{|ln| "#{' ' * indent}" + ln}.join("\n")
208
- else
209
- "#{' ' * indent}" + verb.to_s
218
+ # older versions of ActiveRecord were adding ': ' before an original query :(
219
+ err_caret_line.prepend(' ') if sql_body[0].start_with?(': ')
220
+ # if mistake is on last string than err_line.last != \n then we need to prepend \n to caret line
221
+ err_caret_line.prepend("\n") unless err_line[-1] == "\n"
222
+ err_caret_line
210
223
  end
211
224
  end
212
225
  end
@@ -229,15 +242,22 @@ module Niceql
229
242
 
230
243
  module ErrorExt
231
244
  def to_s
232
- if Niceql.config.prettify_pg_errors && ActiveRecord::Base.connection_config['adapter'] == 'postgresql'
233
- Prettifier.prettify_err(super)
234
- else
235
- super
236
- end
245
+ # older rails version do not provide sql as a standalone query, instead they
246
+ # deliver joined message
247
+ Niceql.config.prettify_pg_errors ? Prettifier.prettify_err(super, try(:sql) ) : super
237
248
  end
238
249
  end
239
250
 
240
251
  class NiceQLConfig
252
+ def ar_using_pg_adapter?
253
+ return false unless defined?(::ActiveRecord::Base)
254
+
255
+ adapter = ActiveRecord::Base.try(:connection_db_config).try(:adapter) ||
256
+ ActiveRecord::Base.try(:connection_config)&.with_indifferent_access&.dig(:adapter)
257
+
258
+ adapter == 'postgresql'
259
+ end
260
+
241
261
  attr_accessor :pg_adapter_with_nicesql,
242
262
  :indentation_base,
243
263
  :open_bracket_is_newliner,
@@ -250,36 +270,30 @@ module Niceql
250
270
  self.indentation_base = 2
251
271
  self.open_bracket_is_newliner = false
252
272
  self.prettify_active_record_log_output = false
253
- self.prettify_pg_errors = defined? ::ActiveRecord::Base && ActiveRecord::Base.connection_config['adapter'] == 'postgresql'
273
+ self.prettify_pg_errors = ar_using_pg_adapter?
254
274
  end
255
275
  end
256
276
 
257
-
258
277
  def self.configure
259
278
  yield( config )
260
279
 
261
- if config.pg_adapter_with_nicesql
262
- ::ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.include(PostgresAdapterNiceQL)
263
- end
280
+ return unless defined? ::ActiveRecord::Base
264
281
 
265
- if config.prettify_active_record_log_output
266
- ::ActiveRecord::ConnectionAdapters::AbstractAdapter.prepend( AbstractAdapterLogPrettifier )
267
- end
282
+ ::ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.include(PostgresAdapterNiceQL) if config.pg_adapter_with_nicesql
268
283
 
269
- if config.prettify_pg_errors
270
- ::ActiveRecord::StatementInvalid.include( Niceql::ErrorExt )
271
- end
284
+ ::ActiveRecord::ConnectionAdapters::AbstractAdapter.prepend( AbstractAdapterLogPrettifier ) if config.prettify_active_record_log_output
285
+
286
+ ::ActiveRecord::StatementInvalid.include( Niceql::ErrorExt ) if config.prettify_pg_errors && config.ar_using_pg_adapter?
272
287
  end
273
288
 
274
289
  def self.config
275
290
  @config ||= NiceQLConfig.new
276
291
  end
277
292
 
278
- if defined? ::ActiveRecord::Base
279
- ::ActiveRecord::Base.extend ArExtentions
280
- [::ActiveRecord::Relation, ::ActiveRecord::Associations::CollectionProxy].each { |klass| klass.send(:include, ArExtentions) }
293
+ if defined? ::ActiveRecord
294
+ [::ActiveRecord::Relation,
295
+ ::Arel::TreeManager,
296
+ ::Arel::Nodes::Node].each { |klass| klass.send(:include, ArExtentions) }
281
297
  end
282
298
 
283
299
  end
284
-
285
-
data/niceql.gemspec CHANGED
@@ -9,8 +9,8 @@ Gem::Specification.new do |spec|
9
9
  spec.authors = ["alekseyl"]
10
10
  spec.email = ["leshchuk@gmail.com"]
11
11
 
12
- spec.summary = %q{This is simple and nice sql prettifier, it splits, indent and colorize SQL query and PG errors if any }
13
- spec.description = %q{This is simple and nice sql prettifier, it splits, indent and colorize SQL query and PG error if any }
12
+ spec.summary = %q{This is simple and nice gem for sql prettifying and formatting. Niceql splits, indent and colorize SQL query and PG errors if any }
13
+ spec.description = %q{This is simple and nice gem for sql prettifying and formatting. Niceql splits, indent and colorize SQL query and PG errors if any. Seemless activerecord integration }
14
14
  spec.homepage = "https://github.com/alekseyl/niceql"
15
15
  spec.license = "MIT"
16
16
 
@@ -30,12 +30,15 @@ Gem::Specification.new do |spec|
30
30
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
31
31
  spec.require_paths = ["lib"]
32
32
 
33
- spec.required_ruby_version = '>= 2.3'
33
+ spec.required_ruby_version = '>= 2.4'
34
+ spec.add_development_dependency "activerecord", ">= 6.1"
35
+
34
36
  spec.add_development_dependency "bundler", ">= 1"
35
- spec.add_development_dependency "rake", "~> 10"
37
+ spec.add_development_dependency "rake", ">= 12.3.3"
36
38
  spec.add_development_dependency "minitest", "~> 5.0"
37
39
 
38
40
  spec.add_development_dependency "differ"
39
41
  spec.add_development_dependency "pry-byebug"
40
42
  spec.add_development_dependency "benchmark-ips"
43
+ spec.add_development_dependency 'sqlite3'
41
44
  end
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: niceql
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.25
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - alekseyl
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-04-13 00:00:00.000000000 Z
11
+ date: 2021-11-01 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activerecord
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '6.1'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '6.1'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: bundler
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -28,16 +42,16 @@ dependencies:
28
42
  name: rake
29
43
  requirement: !ruby/object:Gem::Requirement
30
44
  requirements:
31
- - - "~>"
45
+ - - ">="
32
46
  - !ruby/object:Gem::Version
33
- version: '10'
47
+ version: 12.3.3
34
48
  type: :development
35
49
  prerelease: false
36
50
  version_requirements: !ruby/object:Gem::Requirement
37
51
  requirements:
38
- - - "~>"
52
+ - - ">="
39
53
  - !ruby/object:Gem::Version
40
- version: '10'
54
+ version: 12.3.3
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: minitest
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -94,8 +108,23 @@ dependencies:
94
108
  - - ">="
95
109
  - !ruby/object:Gem::Version
96
110
  version: '0'
97
- description: 'This is simple and nice sql prettifier, it splits, indent and colorize
98
- SQL query and PG error if any '
111
+ - !ruby/object:Gem::Dependency
112
+ name: sqlite3
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ description: 'This is simple and nice gem for sql prettifying and formatting. Niceql
126
+ splits, indent and colorize SQL query and PG errors if any. Seemless activerecord
127
+ integration '
99
128
  email:
100
129
  - leshchuk@gmail.com
101
130
  executables: []
@@ -119,7 +148,6 @@ files:
119
148
  - lib/generators/niceql/install_generator.rb
120
149
  - lib/generators/templates/niceql_initializer.rb
121
150
  - lib/niceql.rb
122
- - lib/niceql/string.rb
123
151
  - lib/niceql/version.rb
124
152
  - niceql.gemspec
125
153
  - to_niceql.png
@@ -128,7 +156,7 @@ licenses:
128
156
  - MIT
129
157
  metadata:
130
158
  allowed_push_host: https://rubygems.org
131
- post_install_message:
159
+ post_install_message:
132
160
  rdoc_options: []
133
161
  require_paths:
134
162
  - lib
@@ -136,17 +164,16 @@ required_ruby_version: !ruby/object:Gem::Requirement
136
164
  requirements:
137
165
  - - ">="
138
166
  - !ruby/object:Gem::Version
139
- version: '2.3'
167
+ version: '2.4'
140
168
  required_rubygems_version: !ruby/object:Gem::Requirement
141
169
  requirements:
142
170
  - - ">="
143
171
  - !ruby/object:Gem::Version
144
172
  version: '0'
145
173
  requirements: []
146
- rubyforge_project:
147
- rubygems_version: 2.7.6
148
- signing_key:
174
+ rubygems_version: 3.0.9
175
+ signing_key:
149
176
  specification_version: 4
150
- summary: This is simple and nice sql prettifier, it splits, indent and colorize SQL
151
- query and PG errors if any
177
+ summary: This is simple and nice gem for sql prettifying and formatting. Niceql splits,
178
+ indent and colorize SQL query and PG errors if any
152
179
  test_files: []
data/lib/niceql/string.rb DELETED
@@ -1,5 +0,0 @@
1
- class String
2
- def match?(pattern)
3
- self =~ pattern
4
- end
5
- end unless String.method_defined?(:match?)