From 67e8b0a2d241d10666546c7da635f41884e3b504 Mon Sep 17 00:00:00 2001 From: Ryan Lue Date: Fri, 25 May 2018 10:54:21 +0800 Subject: [PATCH] Add max_allowed_packet check to MySQL initializer (fixes #2034) --- config/initializers/db_preferences_mysql.rb | 109 ++++++++++++------ .../initializers/db_preferences_postgresql.rb | 44 ++++--- 2 files changed, 98 insertions(+), 55 deletions(-) diff --git a/config/initializers/db_preferences_mysql.rb b/config/initializers/db_preferences_mysql.rb index 9de0ac255..31bb30117 100644 --- a/config/initializers/db_preferences_mysql.rb +++ b/config/initializers/db_preferences_mysql.rb @@ -1,40 +1,77 @@ -# mysql -if ActiveRecord::Base.connection_config[:adapter] == 'mysql2' - Rails.application.config.db_4bytes_utf8 = false - Rails.application.config.db_null_byte = true +return if ActiveRecord::Base.connection_config[:adapter] != 'mysql2' - # mysql version check - # mysql example: "5.7.3" - # mariadb example: "10.1.17-MariaDB" - server_version = ActiveRecord::Base.connection.select_rows('SHOW VARIABLES LIKE \'version\'')[0][1] - raise 'Unable to retrive database version' if !server_version - (server_version, server_vendor) = server_version.split('-') - if !server_vendor - server_vendor = 'MySQL' +Rails.application.config.db_4bytes_utf8 = false +Rails.application.config.db_null_byte = true +connection = ActiveRecord::Base.connection + +# rubocop:disable Rails/Output +# rubocop:disable Rails/Exit +# rubocop:disable Layout/IndentHeredoc + +# Version check -------------------------------------------------------------- +# mysql example: "5.7.3" +# mariadb example: "10.1.17-MariaDB" +server_version = connection.execute('SELECT @@version;').first.first +raise 'Unable to retrive database version' if server_version.blank? +version_number = Gem::Version.new(server_version.split('-').first) +vendor = server_version.split('-').second || 'MySQL' + +case vendor +when 'MySQL' + if version_number < Gem::Version.new('5.6') + printf "\e[31m" # ANSI red + puts <<~MSG + Error: Incompatible database backend version + (MySQL 5.6+ required; #{version_number} found) + MSG + printf "\e[0m" # ANSI normal + exit 1 end - (major, minor) = server_version.split('.') - if server_vendor == 'MySQL' - if major.to_i < 5 || (major.to_i == 5 && minor.to_i < 6) - # rubocop:disable Rails/Output - # rubocop:disable Rails/Exit - p '+++++++++++++++++++++++++++++++++++++++++++++++++++++' - p '+ I\'m sorry, MySQL 5.6+ is required +' - p '+++++++++++++++++++++++++++++++++++++++++++++++++++++' - exit 1 - # rubocop:enable Rails/Exit - # rubocop:enable Rails/Output - end - - elsif server_vendor == 'MariaDB' - if major.to_i < 10 - # rubocop:disable Rails/Output - # rubocop:disable Rails/Exit - p '+++++++++++++++++++++++++++++++++++++++++++++++++++++' - p '+ I\'m sorry, MariaDB 10.0+ is required +' - p '+++++++++++++++++++++++++++++++++++++++++++++++++++++' - exit 1 - # rubocop:enable Rails/Exit - # rubocop:enable Rails/Output - end +when 'MariaDB' + if version_number < Gem::Version.new('10.0') + printf "\e[31m" # ANSI red + puts <<~MSG + Error: Incompatible database backend version + (MariaDB 10.0+ required; #{version_number} found) + MSG + printf "\e[0m" # ANSI normal + exit 1 end end + +# Configuration check -------------------------------------------------------- +# Before MySQL 8.0, the default value of max_allowed_packet was 1MB - 4MB, +# which is impractically small and can lead to failures processing emails. +# +# See https://github.com/zammad/zammad/issues/1759 +# https://github.com/zammad/zammad/issues/1970 +# https://github.com/zammad/zammad/issues/2034 +max_allowed_packet = connection.execute('SELECT @@max_allowed_packet;').first.first +max_allowed_packet_mb = max_allowed_packet / 1024 / 1024 + +if max_allowed_packet_mb <= 4 + printf "\e[31m" # ANSI red + puts <<~MSG + Error: Database config value 'max_allowed_packet' too small (#{max_allowed_packet_mb}MB) + Please increase this value in your #{vendor} configuration (64MB+ recommended). + MSG + printf "\e[0m" # ANSI normal + exit 1 +end + +if connection.execute("SHOW tables LIKE 'settings';").any? && + Setting.get('postmaster_max_size').present? && + Setting.get('postmaster_max_size') > max_allowed_packet_mb + printf "\e[33m" # ANSI yellow + puts <<~MSG + Warning: Database config value 'max_allowed_packet' less than Zammad setting 'Maximum Email Size' + Zammad will fail to process emails (both incoming and outgoing) + larger than the value of 'max_allowed_packet' (#{max_allowed_packet_mb}MB). + Please increase this value in your #{vendor} configuration accordingly. + MSG + printf "\e[0m" # ANSI normal +end + +# rubocop:enable Rails/Exit +# rubocop:enable Rails/Output +# rubocop:enable Layout/IndentHeredoc diff --git a/config/initializers/db_preferences_postgresql.rb b/config/initializers/db_preferences_postgresql.rb index b62f7082c..72e6e91e7 100644 --- a/config/initializers/db_preferences_postgresql.rb +++ b/config/initializers/db_preferences_postgresql.rb @@ -1,23 +1,29 @@ -# postgresql -if ActiveRecord::Base.connection_config[:adapter] == 'postgresql' - Rails.application.config.db_case_sensitive = true - Rails.application.config.db_like = 'ILIKE' - Rails.application.config.db_null_byte = false +return if ActiveRecord::Base.connection_config[:adapter] != 'postgresql' - # postgresql version check - # example output: "9.5.0" - server_version = ActiveRecord::Base.connection.select_rows('SHOW server_version;')[0][0] - (major, minor) = server_version.split('.') - if major.to_i < 9 || (major.to_i == 9 && minor.to_i < 1) +Rails.application.config.db_case_sensitive = true +Rails.application.config.db_like = 'ILIKE' +Rails.application.config.db_null_byte = false - # rubocop:disable Rails/Output - # rubocop:disable Rails/Exit - p '+++++++++++++++++++++++++++++++++++++++++++++++++++++' - p '+ I\'m sorry, PostgreSQL 9.1+ is required +' - p '+++++++++++++++++++++++++++++++++++++++++++++++++++++' - exit 1 - # rubocop:enable Rails/Exit - # rubocop:enable Rails/Output +# rubocop:disable Rails/Output +# rubocop:disable Rails/Exit +# rubocop:disable Layout/IndentHeredoc - end +# Version check -------------------------------------------------------------- +# example output: "9.5.0" +# "10.3 (Debian 10.3-2)" +server_version = ActiveRecord::Base.connection.execute('SHOW server_version;').first['server_version'] +version_number = Gem::Version.new(server_version.split.first) + +if version_number < Gem::Version.new('9.1') + printf "\e[31m" # ANSI red + puts <<~MSG + Error: Incompatible database backend version + (PostgreSQL 9.1+ required; #{version_number} found) + MSG + printf "\e[0m" # ANSI normal + exit 1 end + +# rubocop:enable Rails/Exit +# rubocop:enable Rails/Output +# rubocop:enable Layout/IndentHeredoc