simple-sql 0.4.28 → 0.4.29

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: 0d15e3cf80cc7d5cf308b674a55712a02878e45d1b25b7771248dc020f930d80
4
- data.tar.gz: 258e8a8f695c80a4b630431371689162607aa08d204aea15333f3ad1687565c7
3
+ metadata.gz: 2f70bf7c7bf33282cf573be0fe9371aab9839a7a2fb6e4b3266827871e667575
4
+ data.tar.gz: 5d857fdc4905fb3e5d40b6f51c1e978b4f92b3d7db30a133266d1c0daa72ce63
5
5
  SHA512:
6
- metadata.gz: ee750f741f4bffce5bba59eb938b9fd4ff21854c1ffa1d3b506814a83659a640de508c77cacaf18ca7124f2c3deb684fd3fad239c3337c808b9cf162a770e85c
7
- data.tar.gz: 4f31769ed4cb0a30b18e2864a224d0c87b772439bd6ca3660a44f427b8d0568633a3104931c523dc26160a314a58d814eba71e87b0b1d98b0dec55420ecfed4c
6
+ metadata.gz: 4626339a32bbad1585a8a50b746a55f939ecaf5f671d8b2511b4261446221c8a0be1ef9d2bcfd6193fef5427b3e0a7544af1c25362edca54c8e298f8bfb9d186
7
+ data.tar.gz: 994ddacac8809d15605e6a336699135d7c40361bdf6d7e9e667d618889e92f444b249cb228bf5e84d411762900c74651167d6c65ee6168b41c527baaca1f6bc0
data/.rubocop.yml CHANGED
@@ -10,7 +10,7 @@ AllCops:
10
10
  - 'Rakefile'
11
11
 
12
12
  Metrics/LineLength:
13
- Max: 120
13
+ Max: 140
14
14
 
15
15
  Metrics/MethodLength:
16
16
  Max: 20
@@ -72,3 +72,7 @@ Style/IfUnlessModifier:
72
72
 
73
73
  Style/PerlBackrefs:
74
74
  Enabled: false
75
+
76
+ Style/TrailingUnderscoreVariable:
77
+ Enabled: false
78
+
@@ -1 +1,3 @@
1
+ # rubocop:disable Naming/FileName
2
+
1
3
  # This file is loaded when running bin/console.
@@ -1,6 +1,7 @@
1
1
  # rubocop:disable Metrics/AbcSize
2
2
  # rubocop:disable Metrics/CyclomaticComplexity
3
3
  # rubocop:disable Metrics/PerceivedComplexity
4
+ # rubocop:disable Layout/AlignHash
4
5
 
5
6
  # private
6
7
  module Simple::SQL::Config
@@ -12,7 +12,7 @@ module Simple::SQL::ConnectionAdapter
12
12
  # arguments - since the pg client does not support this - but it allows to
13
13
  # run multiple sql statements separated by ";"
14
14
  def exec(sql)
15
- Logging.yield_logged sql do
15
+ Logging.with_logged_query sql do
16
16
  raw_connection.exec sql
17
17
  end
18
18
  end
@@ -33,6 +33,7 @@ module Simple::SQL::ConnectionAdapter
33
33
 
34
34
  def all(sql, *args, into: nil, &block)
35
35
  raise ArgumentError, "all no longer support blocks, use each instead." if block
36
+
36
37
  rows = []
37
38
  my_pg_source_oid = nil
38
39
 
@@ -67,6 +68,7 @@ module Simple::SQL::ConnectionAdapter
67
68
  # Runs a query and prints the results via "table_print"
68
69
  def print(sql, *args, into: nil)
69
70
  raise ArgumentError, "You cannot call Simple::SQL.print with into: #{into.inspect}" unless into.nil?
71
+
70
72
  require "table_print"
71
73
  records = all sql, *args, into: Hash
72
74
  tp records
@@ -117,7 +119,7 @@ module Simple::SQL::ConnectionAdapter
117
119
  sql = sql_or_scope
118
120
  end
119
121
 
120
- Logging.yield_logged sql, *args do
122
+ Logging.with_logged_query sql, *args do
121
123
  raw_connection.exec_params(sql, Encoder.encode_args(raw_connection, args))
122
124
  end
123
125
  end
@@ -55,6 +55,7 @@ module Simple
55
55
  unless value.is_a?(Fragment)
56
56
  raise ArgumentError, "Pass in override values via SQL.fragment (for #{value.inspect})"
57
57
  end
58
+
58
59
  hsh.update key.to_s => value.to_sql
59
60
  end
60
61
  end
@@ -0,0 +1,60 @@
1
+ module Simple
2
+ module SQL
3
+ module Formatting
4
+ extend self
5
+
6
+ def format(sql, *args)
7
+ sql = format_sql(sql)
8
+
9
+ return sql if args.empty?
10
+
11
+ args = args.map(&:inspect).join(", ")
12
+ sql += " w/args: #{args}"
13
+ sql = sql[0, 98] + "..." if sql.length > 100
14
+ sql
15
+ end
16
+
17
+ def pretty_format(sql, *args)
18
+ sql = if use_pg_format?
19
+ pg_format_sql(sql)
20
+ else
21
+ format_sql(sql)
22
+ end
23
+
24
+ args = args.map(&:inspect).join(", ")
25
+ "#{sql} w/args: #{args}"
26
+ end
27
+
28
+ private
29
+
30
+ def format_sql(sql)
31
+ sql.gsub(/\s*\n\s*/, " ").gsub(/(\A\s+)|(\s+\z)/, "")
32
+ end
33
+
34
+ require "open3"
35
+
36
+ def use_pg_format?
37
+ return @use_pg_format unless @use_pg_format.nil?
38
+
39
+ `which pg_format`
40
+ if $?.exitstatus == 0
41
+ @use_pg_format = true
42
+ else
43
+ Simple::SQL.logger.warn "[sql] simple-sql can use pg_format for logging queries. Please see https://github.com/darold/pgFormatter"
44
+ @use_pg_format = false
45
+ end
46
+ end
47
+
48
+ PG_FORMAT_ARGS = "--function-case 2 --maxlength 15000 --nocomment --spaces 2 --keyword-case 2 --no-comma-end"
49
+
50
+ def pg_format_sql(sql)
51
+ stdin, stdout, _ = Open3.popen2("pg_format #{PG_FORMAT_ARGS} -")
52
+ stdin.print sql
53
+ stdin.close
54
+ formatted = stdout.read
55
+ stdout.close
56
+ formatted
57
+ end
58
+ end
59
+ end
60
+ end
@@ -6,6 +6,7 @@ module Simple::SQL::Helpers::Decoder
6
6
 
7
7
  # rubocop:disable Metrics/AbcSize
8
8
  # rubocop:disable Metrics/CyclomaticComplexity
9
+ # rubocop:disable Naming/UncommunicativeMethodParamName
9
10
  def decode_value(type, s)
10
11
  case type
11
12
  when :unknown then s
@@ -31,7 +32,6 @@ module Simple::SQL::Helpers::Decoder
31
32
  end
32
33
  # rubocop:enable Metrics/AbcSize
33
34
  # rubocop:enable Metrics/CyclomaticComplexity
34
- # rubocop:enable Metrics/MethodLength
35
35
 
36
36
  require "pg_array_parser"
37
37
  extend PgArrayParser
@@ -14,6 +14,7 @@ class Simple::SQL::Helpers::Immutable
14
14
  case object
15
15
  when Array
16
16
  raise ArgumentError, "Object nested too deep (or inner loop?)" if max_depth < 0
17
+
17
18
  object.map { |obj| create obj, max_depth - 1 }
18
19
  when Hash
19
20
  new(object)
@@ -65,6 +66,8 @@ end
65
66
 
66
67
  if $PROGRAM_NAME == __FILE__
67
68
 
69
+ # rubocop:disable Metrics/AbcSize
70
+
68
71
  require "test-unit"
69
72
 
70
73
  class Simple::SQL::Helpers::Immutable::TestCase < Test::Unit::TestCase
@@ -146,5 +149,4 @@ if $PROGRAM_NAME == __FILE__
146
149
  end
147
150
  end
148
151
 
149
- # rubocop:enable Style/ClassAndModuleChildren
150
152
  end
@@ -1,5 +1,7 @@
1
1
  # rubocop:disable Metrics/AbcSize
2
2
  # rubocop:disable Metrics/LineLength
3
+ # rubocop:disable Layout/AlignHash
4
+
3
5
  module Simple
4
6
  module SQL
5
7
  #
@@ -1,3 +1,7 @@
1
+ # rubocop:disable Metrics/AbcSize
2
+
3
+ require_relative "formatting"
4
+
1
5
  module Simple
2
6
  module SQL
3
7
  module Logging
@@ -25,7 +29,10 @@ module Simple
25
29
  return logger if logger
26
30
  end
27
31
 
28
- # returns a stderr_logger
32
+ stderr_logger
33
+ end
34
+
35
+ def stderr_logger
29
36
  @stderr_logger ||= begin
30
37
  logger = Logger.new(STDERR)
31
38
  logger.level = Logger::INFO
@@ -38,25 +45,67 @@ module Simple
38
45
  extend Forwardable
39
46
  delegate [:debug, :info, :warn, :error, :fatal] => :logger
40
47
 
41
- def yield_logged(sql, *args, &_block)
48
+ def slow_query_treshold
49
+ @slow_query_treshold
50
+ end
51
+
52
+ def slow_query_treshold=(slow_query_treshold)
53
+ expect! slow_query_treshold > 0
54
+ @slow_query_treshold = slow_query_treshold
55
+ end
56
+
57
+ def with_logged_query(sql, *args, &_block)
42
58
  r0 = Time.now
43
59
  rv = yield
44
- realtime = Time.now - r0
45
- debug "[sql] %.3f secs: %s" % [realtime, format_query(sql, *args)]
60
+ runtime = Time.now - r0
61
+
62
+ logger.debug do
63
+ "[sql] %.3f secs: %s" % [runtime, Formatting.format(sql, *args)]
64
+ end
65
+
66
+ if slow_query_treshold && runtime > slow_query_treshold
67
+ log_slow_query(sql, *args, runtime: runtime)
68
+ end
69
+
46
70
  rv
47
71
  rescue StandardError => e
48
- realtime = Time.now - r0
49
- warn "[sql] %.3f secs: %s:\n\tfailed with error %s" % [realtime, format_query(sql, *args), e.message]
72
+ runtime = Time.now - r0
73
+ logger.warn do
74
+ "[sql] %.3f secs: %s:\n\tfailed with error %s" % [runtime, Formatting.format(sql, *args), e.message]
75
+ end
76
+
50
77
  raise
51
78
  end
52
79
 
53
80
  private
54
81
 
55
- def format_query(sql, *args)
56
- sql = sql.gsub(/\s*\n\s*/, " ").gsub(/(\A\s+)|(\s+\z)/, "")
57
- return sql if args.empty?
58
- args = args.map(&:inspect).join(", ")
59
- sql + " w/args: #{args}"
82
+ Formatting = ::Simple::SQL::Formatting
83
+
84
+ def log_slow_query(sql, *args, runtime:)
85
+ # Do not try to analyze an EXPLAIN query. This prevents endless recursion here
86
+ # (and, in general, would not be useful anyways.)
87
+ return if sql =~ /^EXPLAIN /
88
+
89
+ log_multiple_lines ::Logger::WARN, prefix: "[sql-slow]" do
90
+ formatted_query = Formatting.pretty_format(sql, *args)
91
+ query_plan = ::Simple::SQL.all "EXPLAIN ANALYZE #{sql}", *args
92
+
93
+ <<~MSG
94
+ === slow query detected: (#{'%.3f secs' % runtime}) ===================================================================================
95
+ #{formatted_query}
96
+ --- query plan: -------------------------------------------------------------------
97
+ #{query_plan.join("\n")}
98
+ ===================================================================================
99
+ MSG
100
+ end
101
+ end
102
+
103
+ def log_multiple_lines(level, str = nil, prefix:)
104
+ logger.log(level) do
105
+ str = yield if str.nil?
106
+ str = str.gsub("\n", "\n#{prefix} ") if prefix
107
+ str
108
+ end
60
109
  end
61
110
  end
62
111
  end
@@ -41,7 +41,7 @@ module Simple
41
41
  SELECT table_schema || '.' || table_name AS name, *
42
42
  FROM information_schema.tables
43
43
  WHERE table_schema=$1
44
- SQL
44
+ SQL
45
45
  records_by_attr(recs, :name)
46
46
  end
47
47
 
@@ -2,6 +2,7 @@
2
2
  # rubocop:disable Metrics/MethodLength
3
3
  # rubocop:disable Metrics/ParameterLists
4
4
  # rubocop:disable Style/GuardClause
5
+ # rubocop:disable Naming/UncommunicativeMethodParamName
5
6
 
6
7
  require "active_support/core_ext/string/inflections"
7
8
 
@@ -164,6 +165,7 @@ module ::Simple::SQL::Result::AssociationLoader # :nodoc:
164
165
  if order_by || limit
165
166
  raise ArgumentError, "#{association.inspect} is a singular association, w/o support for order_by: and limit:"
166
167
  end
168
+
167
169
  preload_belongs_to records, relation, as: as
168
170
  else
169
171
  preload_has_one_or_many records, relation, as: as, order_by: order_by, limit: limit
@@ -1,4 +1,4 @@
1
- # xrubocop:disable Metrics/ParameterLists
1
+ # rubocop:disable Naming/UncommunicativeMethodParamName
2
2
 
3
3
  require_relative "association_loader"
4
4
  require "simple/sql/reflection"
@@ -1,5 +1,3 @@
1
-
2
-
3
1
  class Simple::SQL::Scope
4
2
  def order_by(sql_fragment)
5
3
  duplicate.send(:order_by!, sql_fragment)
@@ -1,5 +1,5 @@
1
1
  module Simple
2
2
  module SQL
3
- VERSION = "0.4.28"
3
+ VERSION = "0.4.29"
4
4
  end
5
5
  end
data/simple-sql.gemspec CHANGED
@@ -38,7 +38,7 @@ Gem::Specification.new do |gem|
38
38
  gem.add_development_dependency 'pg', '0.20'
39
39
  gem.add_development_dependency 'rake', '~> 11'
40
40
  gem.add_development_dependency 'rspec', '~> 3.7'
41
- gem.add_development_dependency 'rubocop', '~> 0.52.1'
41
+ gem.add_development_dependency 'rubocop', '~> 0.61.1'
42
42
  gem.add_development_dependency 'database_cleaner', '~> 1'
43
43
  gem.add_development_dependency 'simplecov', '~> 0'
44
44
  gem.add_development_dependency 'awesome_print', '~> 0'
data/vendor/.gitignore ADDED
@@ -0,0 +1 @@
1
+ pgFormatter-3.1
data/vendor/Makefile ADDED
@@ -0,0 +1,4 @@
1
+ pgFormatter-3.1:
2
+ curl -L -O https://github.com/darold/pgFormatter/archive/v3.1.tar.gz
3
+ tar xvfz v3.1.tar.gz
4
+ cd pgFormatter-3.1 && perl Makefile.PL && make && sudo make install
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: simple-sql
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.28
4
+ version: 0.4.29
5
5
  platform: ruby
6
6
  authors:
7
7
  - radiospiel
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2018-12-21 00:00:00.000000000 Z
12
+ date: 2018-12-23 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: pg_array_parser
@@ -115,14 +115,14 @@ dependencies:
115
115
  requirements:
116
116
  - - "~>"
117
117
  - !ruby/object:Gem::Version
118
- version: 0.52.1
118
+ version: 0.61.1
119
119
  type: :development
120
120
  prerelease: false
121
121
  version_requirements: !ruby/object:Gem::Requirement
122
122
  requirements:
123
123
  - - "~>"
124
124
  - !ruby/object:Gem::Version
125
- version: 0.52.1
125
+ version: 0.61.1
126
126
  - !ruby/object:Gem::Dependency
127
127
  name: database_cleaner
128
128
  requirement: !ruby/object:Gem::Requirement
@@ -203,6 +203,7 @@ files:
203
203
  - lib/simple/sql/connection.rb
204
204
  - lib/simple/sql/connection_adapter.rb
205
205
  - lib/simple/sql/duplicate.rb
206
+ - lib/simple/sql/formatting.rb
206
207
  - lib/simple/sql/helpers.rb
207
208
  - lib/simple/sql/helpers/decoder.rb
208
209
  - lib/simple/sql/helpers/encoder.rb
@@ -245,6 +246,8 @@ files:
245
246
  - spec/support/004_simplecov.rb
246
247
  - spec/support/model/user.rb
247
248
  - tasks/release.rake
249
+ - vendor/.gitignore
250
+ - vendor/Makefile
248
251
  homepage: http://github.com/radiospiel/simple-sql
249
252
  licenses: []
250
253
  metadata: {}