111 lines
3.7 KiB
Ruby
111 lines
3.7 KiB
Ruby
|
module Carto
|
||
|
module Db
|
||
|
class UserSchemaMover
|
||
|
# Approach: move object by object (tables, views, materialized and functions)
|
||
|
STEPS_STRATEGY = :move_schema_content_step_by_step
|
||
|
|
||
|
STRATEGIES = [STEPS_STRATEGY].freeze
|
||
|
|
||
|
def initialize(user)
|
||
|
@user = user
|
||
|
end
|
||
|
|
||
|
def default_strategy
|
||
|
STEPS_STRATEGY
|
||
|
end
|
||
|
|
||
|
def move_objects(new_schema, strategy = default_strategy)
|
||
|
raise "Not valid: #{strategy}" unless STRATEGIES.include?(strategy)
|
||
|
|
||
|
old_schema = @user.database_schema
|
||
|
|
||
|
@user.database_schema = new_schema
|
||
|
@user.this.update database_schema: new_schema
|
||
|
|
||
|
send(strategy, old_schema, new_schema)
|
||
|
end
|
||
|
|
||
|
private
|
||
|
|
||
|
# Moves the schema by moving tables, views...
|
||
|
def move_schema_content_step_by_step(old_schema, new_schema)
|
||
|
@user.in_database(as: :superuser) do |conn|
|
||
|
database = Database.new(@user.database_name, conn)
|
||
|
database.create_schema(new_schema)
|
||
|
@user.db_service.rebuild_quota_trigger_with_database(conn)
|
||
|
|
||
|
conn.transaction do
|
||
|
@user.real_tables(old_schema).
|
||
|
each { |t| move_table_to_schema(t, conn, old_schema, new_schema) }
|
||
|
|
||
|
views(conn, old_schema).
|
||
|
each { |v| move_view_to_schema(v, conn, old_schema, new_schema) }
|
||
|
|
||
|
materialized_views(conn, old_schema).
|
||
|
each { |v| move_materialized_view_to_schema(v, conn, old_schema, new_schema) }
|
||
|
|
||
|
functions(conn, old_schema).
|
||
|
each { |f| move_function_to_schema(f, conn, old_schema, new_schema) }
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
def move_table_to_schema(table, database, old_schema, new_schema)
|
||
|
old_name = "#{old_schema}.#{table[:relname]}"
|
||
|
|
||
|
was_cartodbfied = cdb_drop_triggers(table, database, old_schema)
|
||
|
|
||
|
database.run(%{ ALTER TABLE #{old_name} SET SCHEMA "#{new_schema}" })
|
||
|
|
||
|
cdb_cartodbfy(table, database, new_schema) if was_cartodbfied
|
||
|
end
|
||
|
|
||
|
def cdb_drop_triggers(table, database, schema)
|
||
|
name = "#{schema}.#{table[:relname]}"
|
||
|
|
||
|
cartodbfied = Carto::UserTable.find_by_user_id_and_name(@user.id, table[:relname]).present?
|
||
|
|
||
|
database.run(%{ SELECT cartodb._CDB_drop_triggers('#{name}'::REGCLASS) }) if cartodbfied
|
||
|
|
||
|
cartodbfied
|
||
|
end
|
||
|
|
||
|
def cdb_cartodbfy(table, database, schema)
|
||
|
name = "#{schema}.#{table[:relname]}"
|
||
|
|
||
|
database.run(%{ SELECT cartodb.CDB_CartodbfyTable('#{schema}'::TEXT, '#{name}'::REGCLASS) })
|
||
|
end
|
||
|
|
||
|
def move_view_to_schema(view, database, old_schema, new_schema)
|
||
|
old_name = "#{old_schema}.#{view.name}"
|
||
|
|
||
|
database.run(%{ ALTER VIEW #{old_name} SET SCHEMA "#{new_schema}" })
|
||
|
end
|
||
|
|
||
|
def move_materialized_view_to_schema(view, database, old_schema, new_schema)
|
||
|
old_name = "#{old_schema}.#{view.name}"
|
||
|
|
||
|
database.run(%{ ALTER MATERIALIZED VIEW #{old_name} SET SCHEMA "#{new_schema}" })
|
||
|
end
|
||
|
|
||
|
def move_function_to_schema(function, database, old_schema, new_schema)
|
||
|
old_name = "#{old_schema}.#{function.name}"
|
||
|
|
||
|
database.run(%{ ALTER FUNCTION #{old_name}(#{function.argument_data_types}) SET SCHEMA "#{new_schema}" })
|
||
|
end
|
||
|
|
||
|
def views(db, schema = @user.database_schema, owner_role = @user.database_username)
|
||
|
Carto::Db::Database.new(@user.database_name, db).views(schema, owner_role, 'v')
|
||
|
end
|
||
|
|
||
|
def materialized_views(db, schema = @user.database_schema, owner_role = @user.database_username)
|
||
|
Carto::Db::Database.new(@user.database_name, db).views(schema, owner_role, 'm')
|
||
|
end
|
||
|
|
||
|
def functions(db, schema = @user.database_schema, owner_role = @user.database_username)
|
||
|
Carto::Db::Database.new(@user.database_name, db).functions(schema, owner_role)
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|