pg_auto_parameterize_duplicate_query_detection.rb

lib/sequel/extensions/pg_auto_parameterize_duplicate_query_detection.rb

The pg_auto_parameterize_duplicate_query_detection extension builds on the pg_auto_parameterize extension, adding support for detecting duplicate queries inside a block that occur at the same location. This is designed mostly to catch duplicate query issues (e.g. N+1 queries) during testing.

To detect duplicate queries inside a block of code, wrap the code with detect_duplicate_queries:

DB.detect_duplicate_queries{your_code}

With this approach, if the test runs code where the same query is executed more than once with the same call stack, a Sequel::Postgres::AutoParameterizeDuplicateQueryDetection::DuplicateQueries exception will be raised.

You can pass the :warn option to detect_duplicate_queries to warn instead of raising. Note that if the block passed to detect_duplicate_queries raises, this extension will warn, and raise the original exception.

For more control, you can pass the :handler option to detect_duplicate_queries. If the :handler option is provided, this extension will call the :handler option with the hash of duplicate query information, and will not raise or warn. This can be useful in production environments, to record duplicate queries for later analysis.

For accuracy, the entire call stack is always used as part of the hash key to determine whether a query is duplicate. However, you can filter the displayed backtrace by using the :backtrace_filter option.

detect_duplicate_queries is concurrency aware, it uses the same approach that Sequel’s default connection pools use. So if you are running multiple threads, detect_duplicate_queries will only report duplicate queries for the current thread (or fiber if the fiber_concurrency extension is used).

When testing applications, it’s probably best to use this to wrap the application being tested. For example, testing with rack-test, if your app is App, you would want to wrap it:

include Rack::Test::Methods

WrappedApp = lambda do |env|
  DB.detect_duplicate_queries{App.call(env)}
end

def app
  WrappedApp
end

It is possible to use this to wrap each separate spec using an around hook, but that can result in false positives when using libraries that have implicit retrying (such as Capybara), as you can have the same call stack for multiple requests.

Related module: Sequel::Postgres::AutoParameterizeDuplicateQueryDetection