niceql 0.1.25 → 0.4.0

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: 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?)