lib/chrono_model/adapter/migrations.rb in chrono_model-1.2.2 vs lib/chrono_model/adapter/migrations.rb in chrono_model-2.0.0
- old
+ new
@@ -1,18 +1,19 @@
+# frozen_string_literal: true
+
module ChronoModel
class Adapter < ActiveRecord::ConnectionAdapters::PostgreSQLAdapter
-
module Migrations
# Creates the given table, possibly creating the temporal schema
# objects if the `:temporal` option is given and set to true.
#
- def create_table(table_name, options = {})
+ def create_table(table_name, **options)
# No temporal features requested, skip
return super unless options[:temporal]
if options[:id] == false
- logger.warn "ChronoModel: Temporal Temporal tables require a primary key."
+ logger.warn 'ChronoModel: Temporal Temporal tables require a primary key.'
logger.warn "ChronoModel: Adding a `__chrono_id' primary key to #{table_name} definition."
options[:id] = '__chrono_id'
end
@@ -24,13 +25,17 @@
end
end
# If renaming a temporal table, rename the history and view as well.
#
- def rename_table(name, new_name)
- return super unless is_chrono?(name)
+ def rename_table(name, new_name, **options)
+ unless is_chrono?(name)
+ return super(name, new_name) if method(:rename_table).super_method.arity == 2
+ return super
+ end
+
clear_cache!
transaction do
# Rename tables
#
@@ -61,82 +66,50 @@
#
# If the `:temporal` option is specified, enables or disables temporal
# features on the given table. Please note that you'll lose your history
# when demoting a temporal table to a plain one.
#
- def change_table(table_name, options = {}, &block)
+ def change_table(table_name, **options, &block)
transaction do
-
# Add an empty proc to support calling change_table without a block.
#
- block ||= proc { }
+ block ||= proc {}
- case options[:temporal]
- when true
- if !is_chrono?(table_name)
+ if options[:temporal]
+ unless is_chrono?(table_name)
chrono_make_temporal_table(table_name, options)
end
drop_and_recreate_public_view(table_name, options) do
- super table_name, options, &block
+ super(table_name, **options, &block)
end
- when false
+ else
if is_chrono?(table_name)
chrono_undo_temporal_table(table_name)
end
- super table_name, options, &block
+ super(table_name, **options, &block)
end
-
end
end
# If dropping a temporal table, drops it from the temporal schema
# adding the CASCADE option so to delete the history, view and triggers.
#
- def drop_table(table_name, *)
+ def drop_table(table_name, **options)
return super unless is_chrono?(table_name)
on_temporal_schema { execute "DROP TABLE #{table_name} CASCADE" }
chrono_drop_trigger_functions_for(table_name)
end
- # If adding an index to a temporal table, add it to the one in the
- # temporal schema and to the history one. If the `:unique` option is
- # present, it is removed from the index created in the history table.
- #
- def add_index(table_name, column_name, options = {})
- return super unless is_chrono?(table_name)
-
- transaction do
- on_temporal_schema { super }
-
- # Uniqueness constraints do not make sense in the history table
- options = options.dup.tap {|o| o.delete(:unique)} if options[:unique].present?
-
- on_history_schema { super table_name, column_name, options }
- end
- end
-
- # If removing an index from a temporal table, remove it both from the
- # temporal and the history schemas.
- #
- def remove_index(table_name, *)
- return super unless is_chrono?(table_name)
-
- transaction do
- on_temporal_schema { super }
- on_history_schema { super }
- end
- end
-
# If adding a column to a temporal table, creates it in the table in
# the temporal schema and updates the triggers.
#
- def add_column(table_name, *)
+ def add_column(table_name, column_name, type, **options)
return super unless is_chrono?(table_name)
transaction do
# Add the column to the temporal table
on_temporal_schema { super }
@@ -164,119 +137,123 @@
# If removing a column from a temporal table, we are forced to drop the
# view, then change the column from the table in the temporal schema and
# eventually recreate the triggers.
#
- def change_column(table_name, *)
+ def change_column(table_name, column_name, type, **options)
return super unless is_chrono?(table_name)
+
drop_and_recreate_public_view(table_name) { super }
end
# Change the default on the temporal schema table.
#
def change_column_default(table_name, *)
return super unless is_chrono?(table_name)
+
on_temporal_schema { super }
end
# Change the null constraint on the temporal schema table.
#
def change_column_null(table_name, *)
return super unless is_chrono?(table_name)
+
on_temporal_schema { super }
end
# If removing a column from a temporal table, we are forced to drop the
# view, then drop the column from the table in the temporal schema and
# eventually recreate the triggers.
#
- def remove_column(table_name, *)
+ def remove_column(table_name, column_name, type = nil, **options)
return super unless is_chrono?(table_name)
+
drop_and_recreate_public_view(table_name) { super }
end
private
- # 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 drop_and_recreate_public_view(table_name, opts = {})
- transaction do
- options = chrono_metadata_for(table_name).merge(opts)
- execute "DROP VIEW #{table_name}"
+ # 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 drop_and_recreate_public_view(table_name, opts = {}, &block)
+ transaction do
+ options = chrono_metadata_for(table_name).merge(opts)
- on_temporal_schema { yield }
+ execute "DROP VIEW #{table_name}"
- # Recreate the triggers
- chrono_public_view_ddl(table_name, options)
- end
- end
+ on_temporal_schema(&block)
- def chrono_make_temporal_table(table_name, options)
- # Add temporal features to this table
- #
- if !primary_key(table_name)
- execute "ALTER TABLE #{table_name} ADD __chrono_id SERIAL PRIMARY KEY"
- end
-
- execute "ALTER TABLE #{table_name} SET SCHEMA #{TEMPORAL_SCHEMA}"
- on_history_schema { chrono_history_table_ddl(table_name) }
+ # Recreate the triggers
chrono_public_view_ddl(table_name, options)
- chrono_copy_indexes_to_history(table_name)
+ end
+ end
- # Optionally copy the plain table data, setting up history
- # retroactively.
- #
- if options[:copy_data]
- chrono_copy_temporal_to_history(table_name, options)
- end
+ def chrono_make_temporal_table(table_name, options)
+ # Add temporal features to this table
+ #
+ unless primary_key(table_name)
+ execute "ALTER TABLE #{table_name} ADD __chrono_id SERIAL PRIMARY KEY"
end
- def chrono_copy_temporal_to_history(table_name, options)
- seq = on_history_schema { serial_sequence(table_name, primary_key(table_name)) }
- from = options[:validity] || '0001-01-01 00:00:00'
+ execute "ALTER TABLE #{table_name} SET SCHEMA #{TEMPORAL_SCHEMA}"
+ on_history_schema { chrono_history_table_ddl(table_name) }
+ chrono_public_view_ddl(table_name, options)
+ chrono_copy_indexes_to_history(table_name)
- execute %[
+ # Optionally copy the plain table data, setting up history
+ # retroactively.
+ #
+ return unless options[:copy_data]
+
+ chrono_copy_temporal_to_history(table_name, options)
+ end
+
+ def chrono_copy_temporal_to_history(table_name, options)
+ seq = on_history_schema { pk_and_sequence_for(table_name).last.to_s }
+ from = options[:validity] || '0001-01-01 00:00:00'
+
+ execute %[
INSERT INTO #{HISTORY_SCHEMA}.#{table_name}
SELECT *,
nextval('#{seq}') AS hid,
tsrange('#{from}', NULL) AS validity,
timezone('UTC', now()) AS recorded_at
FROM #{TEMPORAL_SCHEMA}.#{table_name}
]
- end
+ end
- # Removes temporal features from this table
- #
- def chrono_undo_temporal_table(table_name)
- execute "DROP VIEW #{table_name}"
+ # Removes temporal features from this table
+ #
+ def chrono_undo_temporal_table(table_name)
+ execute "DROP VIEW #{table_name}"
- chrono_drop_trigger_functions_for(table_name)
+ chrono_drop_trigger_functions_for(table_name)
- on_history_schema { execute "DROP TABLE #{table_name}" }
+ on_history_schema { execute "DROP TABLE #{table_name}" }
- default_schema = select_value 'SELECT current_schema()'
- on_temporal_schema do
- if primary_key(table_name) == '__chrono_id'
- execute "ALTER TABLE #{table_name} DROP __chrono_id"
- end
-
- execute "ALTER TABLE #{table_name} SET SCHEMA #{default_schema}"
+ default_schema = select_value 'SELECT current_schema()'
+ on_temporal_schema do
+ if primary_key(table_name) == '__chrono_id'
+ execute "ALTER TABLE #{table_name} DROP __chrono_id"
end
+
+ execute "ALTER TABLE #{table_name} SET SCHEMA #{default_schema}"
end
+ end
- # Renames a table and its primary key sequence name
- #
- def rename_table_and_pk(name, new_name)
- seq = serial_sequence(name, primary_key(name))
- new_seq = seq.sub(name.to_s, new_name.to_s).split('.').last
+ # Renames a table and its primary key sequence name
+ #
+ def rename_table_and_pk(name, new_name)
+ seq = pk_and_sequence_for(name).last.to_s
+ new_seq = seq.sub(name.to_s, new_name.to_s).split('.').last
- execute "ALTER SEQUENCE #{seq} RENAME TO #{new_seq}"
- execute "ALTER TABLE #{name} RENAME TO #{new_name}"
- end
+ execute "ALTER SEQUENCE #{seq} RENAME TO #{new_seq}"
+ execute "ALTER TABLE #{name} RENAME TO #{new_name}"
+ end
# private
end
-
end
end