# frozen_string_literal: truerequire"active_record/scoping/default"require"active_record/scoping/named"moduleActiveRecord# This class is used to create a table that keeps track of values and keys such# as which environment migrations were run in.## This is enabled by default. To disable this functionality set# `use_metadata_table` to false in your database configuration.classInternalMetadata# :nodoc:classNullInternalMetadata# :nodoc:endattr_reader:arel_tabledefinitialize(pool)@pool=pool@arel_table=Arel::Table.new(table_name)enddefprimary_key"key"enddefvalue_key"value"enddeftable_name"#{ActiveRecord::Base.table_name_prefix}#{ActiveRecord::Base.internal_metadata_table_name}#{ActiveRecord::Base.table_name_suffix}"enddefenabled?@pool.db_config.use_metadata_table?enddef[]=(key,value)returnunlessenabled?@pool.with_connectiondo|connection|update_or_create_entry(connection,key,value)endenddef[](key)returnunlessenabled?@pool.with_connectiondo|connection|ifentry=select_entry(connection,key)entry[value_key]endendenddefdelete_all_entriesdm=Arel::DeleteManager.new(arel_table)@pool.with_connectiondo|connection|connection.delete(dm,"#{self.class} Destroy")endenddefcountsm=Arel::SelectManager.new(arel_table)sm.project(*Arel::Nodes::Count.new([Arel.star]))@pool.with_connectiondo|connection|connection.select_values(sm,"#{self.class} Count").firstendenddefcreate_table_and_set_flags(environment,schema_sha1=nil)returnunlessenabled?@pool.with_connectiondo|connection|create_tableupdate_or_create_entry(connection,:environment,environment)update_or_create_entry(connection,:schema_sha1,schema_sha1)ifschema_sha1endend# Creates an internal metadata table with columns +key+ and +value+defcreate_tablereturnunlessenabled?@pool.with_connectiondo|connection|unlessconnection.table_exists?(table_name)connection.create_table(table_name,id: false)do|t|t.string:key,**connection.internal_string_options_for_primary_keyt.string:valuet.timestampsendendendenddefdrop_tablereturnunlessenabled?@pool.with_connectiondo|connection|connection.drop_tabletable_name,if_exists: trueendenddeftable_exists?@pool.schema_cache.data_source_exists?(table_name)endprivatedefupdate_or_create_entry(connection,key,value)entry=select_entry(connection,key)ifentryifentry[value_key]!=valueupdate_entry(connection,key,value)elseentry[value_key]endelsecreate_entry(connection,key,value)endenddefcurrent_time(connection)connection.default_timezone==:utc?Time.now.utc:Time.nowenddefcreate_entry(connection,key,value)im=Arel::InsertManager.new(arel_table)im.insert[[arel_table[primary_key],key],[arel_table[value_key],value],[arel_table[:created_at],current_time(connection)],[arel_table[:updated_at],current_time(connection)]]connection.insert(im,"#{self.class} Create",primary_key,key)enddefupdate_entry(connection,key,new_value)um=Arel::UpdateManager.new(arel_table)um.set[[arel_table[value_key],new_value],[arel_table[:updated_at],current_time(connection)]]um.where(arel_table[primary_key].eq(key))connection.update(um,"#{self.class} Update")enddefselect_entry(connection,key)sm=Arel::SelectManager.new(arel_table)sm.project(Arel::Nodes::SqlLiteral.new("*",retryable: true))sm.where(arel_table[primary_key].eq(Arel::Nodes::BindParam.new(key)))sm.order(arel_table[primary_key].asc)sm.limit=1connection.select_all(sm,"#{self.class} Load").firstendendend