mirror of
https://gitlab.com/gitlab-org/gitlab-foss.git
synced 2025-08-13 13:31:19 +00:00
55 lines
1.5 KiB
Ruby
55 lines
1.5 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require 'rubocop/cop/mixin/active_record_helper'
|
|
require_relative '../../code_reuse_helpers'
|
|
|
|
module RuboCop
|
|
module Cop
|
|
module Database
|
|
# Checks the use of .pluck(:attribute) without setting a limit.
|
|
#
|
|
# @example
|
|
#
|
|
# # bad
|
|
# def all
|
|
# Project.where(user_id: User.pluck(:id))
|
|
# end
|
|
#
|
|
# # good
|
|
# def all(limit)
|
|
# Project.where(user_id: User.limit(limit).pluck(:id))
|
|
# end
|
|
class AvoidUsingPluckWithoutLimit < RuboCop::Cop::Base
|
|
include RuboCop::Cop::ActiveRecordHelper
|
|
include RuboCop::CodeReuseHelpers
|
|
|
|
MSG = 'Avoid using `pluck` without defining a proper `limit`. ' \
|
|
'Querying with too much values inside an `IN` clause can result in database performance degradation. ' \
|
|
'See https://gitlab.com/gitlab-com/gl-infra/production/-/issues/17168'
|
|
|
|
RESTRICT_ON_SEND = %i[pluck].freeze
|
|
|
|
# @!method pluck_with_limit?(node)
|
|
def_node_matcher :pluck_with_limit?, <<~PATTERN
|
|
(send (send _ :limit _) ...)
|
|
PATTERN
|
|
|
|
def on_send(node)
|
|
return unless should_scan?(node)
|
|
|
|
return if pluck_with_limit?(node)
|
|
|
|
add_offense(node.loc.selector)
|
|
end
|
|
|
|
private
|
|
|
|
# It limits the check to ActiveRecord, Models, Finders and Service classes
|
|
def should_scan?(node)
|
|
inherit_active_record_base?(node) || in_model?(node) || in_finder?(node) || in_service_class?(node)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|