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 }