Module: Sequel::Postgres::AutoParameterizeDuplicateQueryDetection
- Defined in:
- lib/sequel/extensions/pg_auto_parameterize_duplicate_query_detection.rb
Overview
Enable detecting duplicate queries inside a block
Defined Under Namespace
Classes: DuplicateQueries
Class Method Summary collapse
Instance Method Summary collapse
-
#detect_duplicate_queries(opts = OPTS, &block) ⇒ Object
Run the duplicate query detector during the block.
-
#execute(sql, opts = OPTS, &block) ⇒ Object
Record each query executed so duplicates can be detected, if queries are being recorded.
-
#ignore_duplicate_queries(&block) ⇒ Object
Ignore (do not record) queries inside given block.
Class Method Details
.extended(db) ⇒ Object
62 63 64 65 66 67 |
# File 'lib/sequel/extensions/pg_auto_parameterize_duplicate_query_detection.rb', line 62 def self.extended(db) db.instance_exec do @duplicate_query_detection_contexts = {} @duplicate_query_detection_mutex = Mutex.new end end |
Instance Method Details
#detect_duplicate_queries(opts = OPTS, &block) ⇒ Object
Run the duplicate query detector during the block. Options:
- :backtrace_filter
-
Regexp used to filter the displayed backtrace.
- :handler
-
If present, called with hash of duplicate query information, instead of raising or warning.
- :warn
-
Always warn instead of raising for duplicate queries.
Note that if you nest calls to this method, only the top level call will respect the passed options.
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 |
# File 'lib/sequel/extensions/pg_auto_parameterize_duplicate_query_detection.rb', line 122 def detect_duplicate_queries(opts=OPTS, &block) current = Sequel.current if state = duplicate_query_recorder_state(current) return change_duplicate_query_recorder_state(state, true, &block) end @duplicate_query_detection_mutex.synchronize do @duplicate_query_detection_contexts[current] = [true, Hash.new(0)] end begin yield rescue Exception => e raise ensure _, queries = @duplicate_query_detection_mutex.synchronize do @duplicate_query_detection_contexts.delete(current) end queries.delete_if{|_,v| v < 2} unless queries.empty? if handler = opts[:handler] handler.call(queries) else backtrace_filter = opts[:backtrace_filter] backtrace_filter_note = backtrace_filter ? " (filtered)" : "" query_info = queries.map do |k,v| backtrace = k[1] backtrace = backtrace.grep(backtrace_filter) if backtrace_filter "times:#{v}\nsql:#{k[0]}\nbacktrace#{backtrace_filter_note}:\n#{backtrace.join("\n")}\n" end = "duplicate queries detected:\n\n#{query_info.join("\n")}" if e || opts[:warn] warn() else raise DuplicateQueries.new(, queries) end end end end end |
#execute(sql, opts = OPTS, &block) ⇒ Object
Record each query executed so duplicates can be detected, if queries are being recorded.
85 86 87 88 89 90 91 92 93 |
# File 'lib/sequel/extensions/pg_auto_parameterize_duplicate_query_detection.rb', line 85 def execute(sql, opts=OPTS, &block) record, queries = duplicate_query_recorder_state if record queries[[sql.is_a?(Symbol) ? sql : sql.to_s, caller].freeze] += 1 end super end |
#ignore_duplicate_queries(&block) ⇒ Object
Ignore (do not record) queries inside given block. This can be useful in situations where you want to run your entire test suite with duplicate query detection, but you have duplicate queries in some parts of your application where it is not trivial to use a different approach. You can mark those specific sections with ignore_duplicate_queries, and still get duplicate query detection for the rest of the application.
102 103 104 105 106 107 108 109 110 |
# File 'lib/sequel/extensions/pg_auto_parameterize_duplicate_query_detection.rb', line 102 def ignore_duplicate_queries(&block) if state = duplicate_query_recorder_state change_duplicate_query_recorder_state(state, false, &block) else # If we are not inside a detect_duplicate_queries block, there is # no need to do anything, since we are not recording queries. yield end end |