Module: OnlineMigrations::Utils
- Defined in:
- lib/online_migrations/utils.rb
Class Method Summary collapse
- .ar_enumerate_columns_in_select_statements ⇒ Object
- .ar_partial_writes? ⇒ Boolean
- .ar_partial_writes_setting ⇒ Object
- .ar_version ⇒ Object
- .define_model(table_name) ⇒ Object
- .developer_env? ⇒ Boolean
- .env ⇒ Object
-
.estimated_count(connection, table_name) ⇒ Object
Returns estimated rows count for a table.
- .find_connection_class(model) ⇒ Object
- .foreign_table_name(ref_name, options) ⇒ Object
-
.index_name(table_name, column_name) ⇒ Object
Implementation is from ActiveRecord.
- .multiple_databases? ⇒ Boolean
- .raise_in_prod_or_say_in_dev(message) ⇒ Object
- .raise_or_say(message) ⇒ Object
- .run_background_migrations_inline? ⇒ Boolean
- .say(message) ⇒ Object
- .shard_names(model) ⇒ Object
- .to_bool(value) ⇒ Object
- .volatile_default?(connection, type, value) ⇒ Boolean
- .volatile_function?(connection, function_name) ⇒ Boolean
- .warn(message) ⇒ Object
Class Method Details
.ar_enumerate_columns_in_select_statements ⇒ Object
101 102 103 104 105 106 107 |
# File 'lib/online_migrations/utils.rb', line 101 def ar_enumerate_columns_in_select_statements if ar_version >= 7 ActiveRecord::Base.enumerate_columns_in_select_statements else false end end |
.ar_partial_writes? ⇒ Boolean
89 90 91 |
# File 'lib/online_migrations/utils.rb', line 89 def ar_partial_writes? ActiveRecord::Base.public_send(ar_partial_writes_setting) end |
.ar_partial_writes_setting ⇒ Object
93 94 95 96 97 98 99 |
# File 'lib/online_migrations/utils.rb', line 93 def ar_partial_writes_setting if Utils.ar_version >= 7.0 "partial_inserts" else "partial_writes" end end |
.ar_version ⇒ Object
9 10 11 |
# File 'lib/online_migrations/utils.rb', line 9 def ar_version ActiveRecord.version.to_s.to_f end |
.define_model(table_name) ⇒ Object
55 56 57 58 59 60 |
# File 'lib/online_migrations/utils.rb', line 55 def define_model(table_name) Class.new(ActiveRecord::Base) do self.table_name = table_name self.inheritance_column = :_type_disabled end end |
.developer_env? ⇒ Boolean
22 23 24 |
# File 'lib/online_migrations/utils.rb', line 22 def developer_env? env == "development" || env == "test" end |
.env ⇒ Object
13 14 15 16 17 18 19 20 |
# File 'lib/online_migrations/utils.rb', line 13 def env if defined?(Rails.env) Rails.env else # default to production for safety ENV["RACK_ENV"] || "production" end end |
.estimated_count(connection, table_name) ⇒ Object
Returns estimated rows count for a table. www.citusdata.com/blog/2016/10/12/count-performance/
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
# File 'lib/online_migrations/utils.rb', line 111 def estimated_count(connection, table_name) quoted_table = connection.quote(table_name) count = connection.select_value(<<~SQL) SELECT (reltuples / COALESCE(NULLIF(relpages, 0), 1)) * (pg_relation_size(#{quoted_table}) / (current_setting('block_size')::integer)) FROM pg_catalog.pg_class WHERE relname = #{quoted_table} AND relnamespace = current_schema()::regnamespace SQL if count count = count.to_i # If the table has never yet been vacuumed or analyzed, reltuples contains -1 # indicating that the row count is unknown. count = 0 if count < 0 count end end |
.find_connection_class(model) ⇒ Object
154 155 156 157 158 159 |
# File 'lib/online_migrations/utils.rb', line 154 def find_connection_class(model) model.ancestors.find do |parent| parent == ActiveRecord::Base || (parent.is_a?(Class) && parent.abstract_class?) end end |
.foreign_table_name(ref_name, options) ⇒ Object
66 67 68 69 70 |
# File 'lib/online_migrations/utils.rb', line 66 def foreign_table_name(ref_name, ) .fetch(:to_table) do ActiveRecord::Base.pluralize_table_names ? ref_name.to_s.pluralize : ref_name end end |
.index_name(table_name, column_name) ⇒ Object
Implementation is from ActiveRecord. This is not needed for ActiveRecord >= 7.1 (github.com/rails/rails/pull/47753).
74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
# File 'lib/online_migrations/utils.rb', line 74 def index_name(table_name, column_name) max_index_name_size = 62 name = "index_#{table_name}_on_#{Array(column_name) * '_and_'}" return name if name.bytesize <= max_index_name_size # Fallback to short version, add hash to ensure uniqueness hashed_identifier = "_#{OpenSSL::Digest::SHA256.hexdigest(name).first(10)}" name = "idx_on_#{Array(column_name) * '_'}" short_limit = max_index_name_size - hashed_identifier.bytesize short_name = name[0, short_limit] "#{short_name}#{hashed_identifier}" end |
.multiple_databases? ⇒ Boolean
173 174 175 176 |
# File 'lib/online_migrations/utils.rb', line 173 def multiple_databases? db_config = ActiveRecord::Base.configurations.configs_for(env_name: env) db_config.reject(&:replica?).size > 1 end |
.raise_in_prod_or_say_in_dev(message) ⇒ Object
43 44 45 46 47 48 49 |
# File 'lib/online_migrations/utils.rb', line 43 def raise_in_prod_or_say_in_dev() if developer_env? say() else raise end end |
.raise_or_say(message) ⇒ Object
35 36 37 38 39 40 41 |
# File 'lib/online_migrations/utils.rb', line 35 def raise_or_say() if developer_env? && !multiple_databases? raise else say() end end |
.run_background_migrations_inline? ⇒ Boolean
178 179 180 181 |
# File 'lib/online_migrations/utils.rb', line 178 def run_background_migrations_inline? run_inline = OnlineMigrations.config.run_background_migrations_inline run_inline && run_inline.call end |
.say(message) ⇒ Object
26 27 28 29 30 31 32 33 |
# File 'lib/online_migrations/utils.rb', line 26 def say() = "[online_migrations] #{}" if (migration = OnlineMigrations.current_migration) migration.say() elsif (logger = ActiveRecord::Base.logger) logger.info() end end |
.shard_names(model) ⇒ Object
161 162 163 164 165 166 167 168 169 170 171 |
# File 'lib/online_migrations/utils.rb', line 161 def shard_names(model) model.ancestors.each do |ancestor| # There is no official method to get shard names from the model. # This is the way that currently is used in ActiveRecord tests themselves. pool_manager = ActiveRecord::Base.connection_handler.send(:get_pool_manager, ancestor.name) # .uniq call is not needed for Active Record 7.1+ # See https://github.com/rails/rails/pull/49284. return pool_manager.shard_names.uniq if pool_manager end end |
.to_bool(value) ⇒ Object
62 63 64 |
# File 'lib/online_migrations/utils.rb', line 62 def to_bool(value) value.to_s.match?(/^true|t|yes|y|1|on$/i) end |
.volatile_default?(connection, type, value) ⇒ Boolean
135 136 137 138 139 140 141 142 |
# File 'lib/online_migrations/utils.rb', line 135 def volatile_default?(connection, type, value) return false if !(value.is_a?(Proc) || (type.to_s == "uuid" && value.is_a?(String))) value = value.call if value.is_a?(Proc) return false if !value.is_a?(String) value.scan(FUNCTION_CALL_RE).any? { |(function_name)| volatile_function?(connection, function_name.downcase) } end |
.volatile_function?(connection, function_name) ⇒ Boolean
144 145 146 147 148 149 150 151 152 |
# File 'lib/online_migrations/utils.rb', line 144 def volatile_function?(connection, function_name) query = <<~SQL SELECT provolatile FROM pg_catalog.pg_proc WHERE proname = #{connection.quote(function_name)} SQL connection.select_value(query) == "v" end |
.warn(message) ⇒ Object
51 52 53 |
# File 'lib/online_migrations/utils.rb', line 51 def warn() Kernel.warn("[online_migrations] #{}") end |