lib/chrono_model/adapter.rb in chrono_model-0.9.0 vs lib/chrono_model/adapter.rb in chrono_model-0.9.1

- old
+ new

@@ -150,11 +150,11 @@ FROM #{TEMPORAL_SCHEMA}.#{table_name} ] end end - chrono_alter(table_name) { super table_name, options, &block } + chrono_alter(table_name, options) { super table_name, options, &block } else if options[:temporal] == false && is_chrono?(table_name) # Remove temporal features from this table # execute "DROP VIEW #{table_name}" @@ -565,12 +565,12 @@ _on_temporal_schema { tables }.each do |table_name| next unless is_chrono?(table_name) metadata = chrono_metadata_for(table_name) version = metadata['chronomodel'] - if version.blank? # FIXME - raise Error, "ChronoModel found structures created by a too old version. Cannot upgrade right now." + if version.blank? + upgrade_from_legacy(table_name) end next if version == current logger.info "ChronoModel: upgrading #{table_name} from #{version} to #{current}" @@ -585,10 +585,50 @@ # logger.error message $stderr.puts message end + def upgrade_from_legacy(table_name) + # roses are red + # violets are blue + # and this is the most boring piece of code ever + history_table = "#{HISTORY_SCHEMA}.#{table_name}" + p_pkey = primary_key(table_name) + + execute "ALTER TABLE #{history_table} ADD COLUMN validity tsrange;" + execute """ + UPDATE #{history_table} SET validity = tsrange(valid_from, + CASE WHEN extract(year from valid_to) = 9999 THEN NULL + ELSE valid_to + END + ); + """ + + execute "DROP INDEX #{history_table}_temporal_on_valid_from;" + execute "DROP INDEX #{history_table}_temporal_on_valid_from_and_valid_to;" + execute "DROP INDEX #{history_table}_temporal_on_valid_to;" + execute "DROP INDEX #{history_table}_inherit_pkey" + execute "DROP INDEX #{history_table}_recorded_at" + execute "DROP INDEX #{history_table}_instance_history" + execute "ALTER TABLE #{history_table} DROP CONSTRAINT #{table_name}_valid_from_before_valid_to;" + execute "ALTER TABLE #{history_table} DROP CONSTRAINT #{table_name}_timeline_consistency;" + execute "DROP RULE #{table_name}_upd_first ON #{table_name};" + execute "DROP RULE #{table_name}_upd_next ON #{table_name};" + execute "DROP RULE #{table_name}_del ON #{table_name};" + execute "DROP RULE #{table_name}_ins ON #{table_name};" + execute "DROP TRIGGER history_ins ON #{TEMPORAL_SCHEMA}.#{table_name};" + execute "DROP FUNCTION #{TEMPORAL_SCHEMA}.#{table_name}_ins();" + execute "ALTER TABLE #{history_table} DROP COLUMN valid_from;" + execute "ALTER TABLE #{history_table} DROP COLUMN valid_to;" + + execute "CREATE EXTENSION IF NOT EXISTS btree_gist;" + + chrono_create_view_for(table_name) + _on_history_schema { add_history_validity_constraint(table_name, p_pkey) } + _on_history_schema { chrono_create_history_indexes_for(table_name, p_pkey) } + end + def chrono_metadata_for(table) comment = select_value( "SELECT obj_description(#{quote(table)}::regclass)", "ChronoModel metadata for #{table}") if table_exists?(table) @@ -809,12 +849,12 @@ # In destructive changes, such as removing columns or changing column # types, the view must be dropped and recreated, while the change has # to be applied to the table in the temporal schema. # - def chrono_alter(table_name) + def chrono_alter(table_name, opts = {}) transaction do - options = chrono_metadata_for(table_name) + options = chrono_metadata_for(table_name).merge(opts) execute "DROP VIEW #{table_name}" _on_temporal_schema { yield }