2020-05-04 05:09:36 -04:00
# frozen_string_literal: true
require_relative '../../migration_helpers'
module RuboCop
module Cop
module Migration
2022-09-14 11:12:56 -04:00
class WithLockRetriesDisallowedMethod < RuboCop :: Cop :: Base
2020-05-04 05:09:36 -04:00
include MigrationHelpers
ALLOWED_MIGRATION_METHODS = % i [
create_table
2020-06-26 11:08:45 -04:00
create_hash_partitions
2020-05-04 05:09:36 -04:00
drop_table
add_foreign_key
remove_foreign_key
add_column
remove_column
execute
change_column_default
2020-08-18 08:10:16 -04:00
change_column_null
2020-05-04 05:09:36 -04:00
remove_foreign_key_if_exists
remove_foreign_key_without_error
2021-02-19 19:10:55 -05:00
rename_index
2021-06-28 08:38:12 -04:00
rename_constraint
2020-05-04 05:09:36 -04:00
table_exists?
index_exists_by_name?
foreign_key_exists?
index_exists?
column_exists?
2021-04-06 11:09:23 -04:00
create_trigger_to_sync_tables
2020-05-04 05:09:36 -04:00
] . sort . freeze
MSG = " The method is not allowed to be called within the `with_lock_retries` block, the only allowed methods are: #{ ALLOWED_MIGRATION_METHODS . join ( ', ' ) } "
2020-10-06 05:08:32 -04:00
MSG_ONLY_ONE_FK_ALLOWED = " Avoid adding more than one foreign key within the `with_lock_retries`. See https://docs.gitlab.com/ee/development/migration_style_guide.html # examples "
2020-05-04 05:09:36 -04:00
def_node_matcher :send_node? , << ~ PATTERN
2020-10-06 05:08:32 -04:00
send
PATTERN
def_node_matcher :add_foreign_key? , << ~ PATTERN
( send nil ? :add_foreign_key ... )
2020-05-04 05:09:36 -04:00
PATTERN
def on_block ( node )
block_body = node . body
return unless in_migration? ( node )
return unless block_body
return unless node . method_name == :with_lock_retries
if send_node? ( block_body )
check_node ( block_body )
else
block_body . children . each { | n | check_node ( n ) }
end
end
def check_node ( node )
return unless send_node? ( node )
name = node . children [ 1 ]
2022-09-14 11:12:56 -04:00
add_offense ( node ) unless ALLOWED_MIGRATION_METHODS . include? ( name )
add_offense ( node . loc . selector , message : MSG_ONLY_ONE_FK_ALLOWED ) if multiple_fks? ( node )
2020-10-06 05:08:32 -04:00
end
def multiple_fks? ( node )
return unless add_foreign_key? ( node )
count = node . parent . each_descendant ( :send ) . count do | node |
add_foreign_key? ( node )
end
count > 1
2020-05-04 05:09:36 -04:00
end
end
end
end
end