DEV: Support --skip-max-length-violations arg for remap (#29877)

Allow remap eligible rows to be skipped if new text exceeds column's max length constraint
This commit is contained in:
Selase Krakani 2024-11-25 11:40:51 +00:00 committed by GitHub
parent a20b7fa83f
commit dfa591aeae
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 38 additions and 14 deletions

View File

@ -8,7 +8,8 @@ class DiscourseCLI < Thor
true true
end end
desc "remap [--global,--regex,--force] FROM TO", "Remap a string sequence across all tables" desc "remap [--global,--regex,--force, --skip-max-length-violations] FROM TO",
"Remap a string sequence across all tables"
long_desc <<-TEXT long_desc <<-TEXT
Replace a string sequence FROM with TO across all tables. Replace a string sequence FROM with TO across all tables.
@ -24,6 +25,10 @@ class DiscourseCLI < Thor
"regexp_replace" documentation in the PostgreSQL manual for more "regexp_replace" documentation in the PostgreSQL manual for more
details. details.
With --skip-max-length-violations option, remapping is skipped for rows where
the remapped text exceeds the column's maximum length constraint. This option is
useful for non-critical remaps, allowing you to skip a few violating rows instead
of aborting the entire remap process.
Examples: Examples:
@ -32,8 +37,9 @@ class DiscourseCLI < Thor
discourse remap --regex "\[\/?color(=[^\]]*)*]" "" # removing "color" bbcodes discourse remap --regex "\[\/?color(=[^\]]*)*]" "" # removing "color" bbcodes
TEXT TEXT
option :global, type: :boolean option :global, type: :boolean
option :regex, type: :boolean option :regex, type: :boolean, default: false
option :force, type: :boolean option :force, type: :boolean
option :skip_max_length_violations, type: :boolean, default: false
def remap(from, to) def remap(from, to)
load_rails load_rails
@ -49,22 +55,20 @@ class DiscourseCLI < Thor
puts "WILL RUN ON '#{RailsMultisite::ConnectionManagement.current_db}' DB" puts "WILL RUN ON '#{RailsMultisite::ConnectionManagement.current_db}' DB"
end end
unless options[:force] confirm!("THIS TASK WILL REWRITE DATA") unless options[:force]
puts "THIS TASK WILL REWRITE DATA, ARE YOU SURE (type YES)"
if STDIN.gets.strip.upcase != "YES" if options[:skip_max_length_violations]
puts "aborting." confirm!("WILL SKIP MAX LENGTH VIOLATIONS. THIS MIGHT BE UNSUITABLE FOR CRITICAL REMAPS")
exit 1
end
end end
if options[:global] if options[:global]
RailsMultisite::ConnectionManagement.each_connection do |db| RailsMultisite::ConnectionManagement.each_connection do |db|
puts "", "Remapping tables on #{db}...", "" puts "", "Remapping tables on #{db}...", ""
do_remap(from, to, options[:regex]) do_remap(from, to)
end end
else else
puts "", "Remapping tables on #{RailsMultisite::ConnectionManagement.current_db}...", "" puts "", "Remapping tables on #{RailsMultisite::ConnectionManagement.current_db}...", ""
do_remap(from, to, options[:regex]) do_remap(from, to)
end end
end end
@ -268,18 +272,38 @@ class DiscourseCLI < Thor
private private
def confirm!(message, prompt = "ARE YOU SURE (type YES):")
unless yes?("#{message}, #{prompt}")
puts "aborting."
exit(1)
end
end
def load_rails def load_rails
require File.expand_path(File.dirname(__FILE__) + "/../config/environment") require File.expand_path(File.dirname(__FILE__) + "/../config/environment")
end end
def do_remap(from, to, regex = false) def do_remap(from, to)
begin begin
if regex remap_options = {
DbHelper.regexp_replace(from, to, verbose: true) verbose: true,
skip_max_length_violations: options[:skip_max_length_violations],
}
if options[:regex]
DbHelper.regexp_replace(from, to, **remap_options)
else else
DbHelper.remap(from, to, verbose: true) DbHelper.remap(from, to, **remap_options)
end end
puts "Done", "" puts "Done", ""
rescue PG::StringDataRightTruncation => e
puts <<~TEXT
#{e}
One or more remapped texts exceeded the maximum column length constraint. Either fix the offending
column(s) mentioned in the error above or re-run the script with --skip-max-length-violations to skip these rows.
TEXT
exit(1)
rescue => ex rescue => ex
puts "Error: #{ex}" puts "Error: #{ex}"
puts "The remap has only been partially applied due to the error above. Please re-run the script again." puts "The remap has only been partially applied due to the error above. Please re-run the script again."