Skip to content

Commit

Permalink
Implement the rename_view method
Browse files Browse the repository at this point in the history
  • Loading branch information
gagalago committed Jan 21, 2021
1 parent 72da84c commit ae377ce
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 15 deletions.
45 changes: 44 additions & 1 deletion lib/scenic/adapters/postgres.rb
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,21 @@ def drop_view(name)
execute "DROP VIEW #{quote_table_name(name)};"
end

# Renames a view in the database
#
# This is typically called in a migration via {Statements#rename_view}.
#
# @param from_name The previous name of the view to rename.
# @param to_name The next name of the view to rename.
#
# @return [void]
def rename_view(from_name, to_name)
execute <<~SQL
ALTER VIEW #{quote_table_name(from_name)}
RENAME TO #{quote_table_name(to_name)};
SQL
end

# Creates a materialized view in the database
#
# @param name The name of the materialized view to create
Expand Down Expand Up @@ -183,6 +198,34 @@ def drop_materialized_view(name)
execute "DROP MATERIALIZED VIEW #{quote_table_name(name)};"
end

# Renames a materialized view in the database
#
# This is typically called in a migration via {Statements#rename_view}.
#
# @param from_name The previous name of the materialized view to rename.
# @param to_name The next name of the materialized view to rename.
# @raise [MaterializedViewsNotSupportedError] if the version of Postgres
# in use does not support materialized views.
#
# @return [void]
def rename_materialized_view(from_name, to_name, rename_indexes: false)
raise_unless_materialized_views_supported
execute <<~SQL
ALTER MATERIALIZED VIEW #{quote_table_name(from_name)}
RENAME TO #{quote_table_name(to_name)};
SQL

if rename_indexes
Indexes.new(connection: connection)
.on(to_name)
.map(&:index_name)
.select { |name| name.match?(from_name) }
.each do |name|
rename_index to_name, name, name.sub(from_name, to_name)
end
end
end

# Refreshes a materialized view from its SQL schema.
#
# This is typically called from application code via {Scenic.database}.
Expand Down Expand Up @@ -225,7 +268,7 @@ def refresh_materialized_view(name, concurrently: false, cascade: false)
private

attr_reader :connectable
delegate :execute, :quote_table_name, to: :connection
delegate :execute, :quote_table_name, :rename_index, to: :connection

def connection
Connection.new(connectable.connection)
Expand Down
27 changes: 13 additions & 14 deletions lib/scenic/command_recorder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,9 @@
module Scenic
# @api private
module CommandRecorder
def create_view(*args)
record(:create_view, args)
end

def drop_view(*args)
record(:drop_view, args)
end

def update_view(*args)
record(:update_view, args)
end

def replace_view(*args)
record(:replace_view, args)
METHODS = %i[create_view drop_view update_view replace_view rename_view]
METHODS.each do |method|
define_method(method) { |*args| record(method, args) }
end

def invert_create_view(args)
Expand All @@ -36,6 +25,16 @@ def invert_replace_view(args)
perform_scenic_inversion(:replace_view, args)
end

def invert_rename_view(args)
options = args.extract_options!
old_name, new_name = args

args = [new_name, old_name]
args << options unless options.empty?

[:rename_view, args]
end

private

def perform_scenic_inversion(method, args)
Expand Down
33 changes: 33 additions & 0 deletions lib/scenic/statements.rb
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,31 @@ def replace_view(name, version: nil, revert_to_version: nil, materialized: false
Scenic.database.replace_view(name, sql_definition)
end

# Rename a database view by name.
#
# @param from_name [String, Symbol] The previous name of the database view.
# @param from_name [String, Symbol] The next name of the database view.
# @param materialized [Boolean, Hash] True if updating a materialized view.
# Set to { rename_indexes: true } to rename materialized view indexes
# by substituing in their name the previous view name
# to the next view name. Defaults to false.
# @return The database response from executing the rename statement.
#
# @example Rename a view
# drop_view(:engggggement_reports, :engagement_reports)
#
def rename_view(from_name, to_name, materialized: false)
if materialized
Scenic.database.rename_materialized_view(
from_name,
to_name,
rename_indexes: rename_indexes(materialized),
)
else
Scenic.database.rename_view(from_name, to_name)
end
end

private

def definition(name, version)
Expand All @@ -159,5 +184,13 @@ def no_data(materialized)
false
end
end

def rename_indexes(materialized)
if materialized.is_a?(Hash)
materialized.fetch(:rename_indexes, false)
else
false
end
end
end
end

0 comments on commit ae377ce

Please sign in to comment.